回到目录

在MVC,EF,LINQ环境里,我们经常会用到DataModel(DO)和ViewModel(VO),可能对于它们的属性校验我们会采用特性的方式,当然这很直观,就连微软的DEMO也是如些,一般是这样的代码

        /// <summary>
/// 机构ID
/// </summary>
[DisplayName("机构ID")]
public int AgentId { get; set; }
/// <summary>
/// 机构名称
/// </summary>
[DisplayName("机构名称")]
[MaxLength()]
public string AgentName { get; set; }
/// <summary>
/// 机构负责人
/// </summary>
[DisplayName("机构负责人")]
[MaxLength()]
public string AgentUser { get; set; }

而这种设计方式给我们以后的维护带来很多问题,具体大叔总结一下:

  1. 与数据实体混在一起,不利用扩展,更新实体你加的特性可能会丢失
  2. 如果有多个VO,那么你需要把它加到具体的VO上,因为DO的语义可能不太明确
  3. 不方便迁移,它与ModelState耦合太高
  4. 从面向对象的角度来看,它的职责太单一,引起变因太多

综上所述,FluentValidation就诞生了!

nuget上去安装它:install-package FluentValidation

你的一个实体类,可以添加多个检验类,这相当于可以有多种检验类去装饰一个实体类,我觉得挺好!

   public class CreateUserEventValidator : AbstractValidator<CreateUserEvent>
{
public CreateUserEventValidator()
{
RuleFor(command => command.UserName).NotEmpty().Length(, ).WithMessage("用户名升序为5-20字符!");
RuleFor(command => command.Email).NotEmpty().EmailAddress().WithMessage("不是有效的Email!");
RuleFor(command => command.BirthDay).NotEmpty().Must(i => i < DateTime.Now).WithMessage("你的年紀太小了!");
}
}

使用时,可以通过IsValid,Errors等属性拿到你需要的信息,当然,你也可以把它在命令事件,领域事件上用一下,比如做个验证的装饰器,哪些处理程序要用校验,就通过这个装饰器装饰一下就行了,挺优雅!

   //验证-装饰器
BusManager.Instance.Subscribe(new ValidatorDecorator<CreateUserEvent>(
new UserEventHandler(),
new CreateUserEventValidator()));
//日志-装饰器
BusManager.Instance.Subscribe(new LoggerDecorator<CreateUserEvent>(new UserEventHandler()));
BusManager.Instance.Publish(new CreateUserEvent { UserName = "占占大师5个字" });

装饰器要求你转一个要被装饰的对象和一个装饰器,就可以了。

    /// <summary>
/// 验证装饰器
/// </summary>
/// <typeparam name="TEvent"></typeparam>
[Serializable]
public class ValidatorDecorator<TEvent>
: IBusHandler<TEvent>
where TEvent : IBusData
{
/// <summary>
/// 要被装饰的处理程序
/// </summary>
private readonly IBusHandler<TEvent> _inner;
/// <summary>
/// 校验装饰器集合
/// </summary>
private readonly IValidator<TEvent>[] _validators; /// <summary>
/// 初始化
/// </summary>
/// <param name="inner">要被装饰的处理程序</param>
/// <param name="validators">装饰器</param>
public ValidatorDecorator(IBusHandler<TEvent> inner, params IValidator<TEvent>[] validators)
{
_inner = inner;
_validators = validators;
}
public void Handle(TEvent evt)
{
var failures = _validators
.Select(v => v.Validate(evt))
.SelectMany(result => result.Errors)
.Where(error => error != null)
.ToList(); if (failures.Any())
{
throw new ValidationException("实体校验失败", failures);
} _inner.Handle(evt);
}
}

对于一种知识的学习与理解是需要一些理论基础的,大家可以多看看设计模块,算法导论,.netCLR等书籍!

感谢各位的阅读!

回到目录

EF架构~FluentValidation实体检验与实体分离了的更多相关文章

  1. EF架构~为EF DbContext生成的实体添加注释(T5模板应用)

    回到目录 相关文章系列 第八回 EF架构~将数据库注释添加导入到模型实体类中 第二十一回  EF架构~为EF DbContext生成的实体添加注释(T4模板应用) 第二十二回EF架构~为EF DbCo ...

  2. EF架构~为EF DbContext生成的实体添加注释(T5模板应用)(转载)

    转载地址:http://www.newlifex.com/showtopic-1072.aspx 最近新项目要用Entity Framework 6.x,但是我发现从数据库生成模型时没有生成字段的注释 ...

  3. 【转】EF架构~为EF DbContext生成的实体添加注释(T5模板应用)

    嗨,没法说,EF4的TT模版加上注释后,升级到EF5的TT模版后,注释就不通用了,所以,还得再研究一下,然后把操作方法再分享出来,没辙的微软! T4模版可能有些凌乱,这在T5模版里有了不错的改进,但我 ...

  4. EF架构~AutoMapper对象映射工具简化了实体赋值的过程

    回到目录 AutoMapper是一个.NET的对象映射工具,一般地,我们进行面向服务的开发时,都会涉及到DTO的概念,即数据传输对象,而为了减少系统的负载,一般我们不会把整个表的字段作为传输的数据,而 ...

  5. EF架构~通过EF6的DbCommand拦截器来实现数据库读写分离~终结~配置的优化和事务里读写的统一

    回到目录 本讲是通过DbCommand拦截器来实现读写分离的最后一讲,对之前几篇文章做了一个优化,无论是程序可读性还是实用性上都有一个提升,在配置信息这块,去除了字符串方式的拼接,取而代之的是sect ...

  6. ASP.NET Core搭建多层网站架构【5-网站数据库实体设计及映射配置】

    2020/01/29, ASP.NET Core 3.1, VS2019, EntityFrameworkCore 3.1.1, Microsoft.Extensions.Logging.Consol ...

  7. EF架构~基于EF数据层的实现

    回到目录 之前写过关于实现一个完整的EF架构的文章,文章的阅读量也是满大的,自己很欣慰,但是,那篇文章是我2011年写的,所以,技术有些不成熟,所以今天把我的2014年写的EF底层架构公开一下,这个架 ...

  8. EF架构~CodeFirst数据迁移与防数据库删除

    回到目录 本文介绍两个概念,防数据库自动删除,这是由于在code first模式下,当数据实体发生变化时,会对原来数据库进行删除,并将新数据表添加进来,但这对于我们的运营环境数据库,是万万不能接受的, ...

  9. EF架构~过滤导航属性等,拼接SQL字符串

    拼接T-SQL串,并使它具有通用性 好处:与服务器建立一次连接,给服务器发一条SQL命令,即可实现 代码如下: 1 /// <summary> 2 /// 构建Insert语句串 3 // ...

随机推荐

  1. Shell脚本学习 - 函数,输入输出重定向,文件

    函数 函数定义 [ function ] funname [()] { action; [return int;] } 定义时可以是function fun(),也可以直接fun(),不带参数 返回值 ...

  2. sql基本语法

    sql基本语法 sql server 查询 多表查询 直接多表查询 select * from st_profiles,st_score_report 上面的语句将会产生两个表的笛卡尔乘积,其中大部分 ...

  3. bindservice与Activity通信

    package com.example.jikangwang.myapplication; import android.content.ComponentName; import android.c ...

  4. MySQL基于左右值编码的树形数据库表结构设计

    MySQL基于左右值编码的树形数据库表结构设计   在关系型数据库中设计树形的数据结构一直是一个十分考验开发者能力的,最常用的方案有主从表方案和继承关系(parent_id)方案.主从表方案的最大缺点 ...

  5. BZOJ5304 : [Haoi2018]字串覆盖

    离线处理所有询问. 对于$r-l\leq 50$的情况: 按照串长从$1$到$51$分别把所有子串按照第一位字符为第一关键字,上一次排序结果为第二关键字进行$O(n)$基数排序. 同理也可以用上一次比 ...

  6. ajaj简介

    1. 什么是ajax? ajax的全称 Asynchronous(异步) JavaScript and XML. ajax是一种用于创建快速动态网页的技术. 主要用于前后台的交互,在前后台的交互中还有 ...

  7. 转 the best for wcf client

    原文:http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-bl ...

  8. RequireJS简单实用说明

    OM前端框架说明 om前端框架采用RequireJS,RequireJS  是一个JavaScript模块加载器.它非常适合在浏览器中使用, 它非常适合在浏览器中使用,但它也可以用在其他脚本环境, 就 ...

  9. Vue 过滤器的使用

    Vue官方文档是这样说的:Vue过滤器用于格式化一些常见的文本. 在实际项目中的使用: 定义过滤器 在src定义一个filter.js文件,里面定义过滤器函数,在最后要使用 exprot defaul ...

  10. Ubuntu 16.04下sublime text3安装

    安装方法 在确保Ubuntu更新了国内镜像源的前提下,使用ppa安装: sudo add-apt-repository ppa:webupd8team/sublime-text-3 sudo apt- ...