• [CAMCOCO][C#]我的系统架构.服务器端.(四)----Model层 实体的自我验证


    这是Model的第二篇,上一篇点这里

    这块完全是扒了@何镇汐大神博客里的教程实现的,在这之前完全没想到数据验证居然可以这样做!!在此表示严重感谢!!!

    点击这里可以去了解这个方法的原理,老胡估计自己是完全说不清楚的了。http://www.cnblogs.com/xiadao521/p/4111815.html

    还是来图上看

    Validation部分,这里是从@何镇汐教程中拔过来的代码,

    老胡只是在_BaseEntityValidation类里面进行了简单的集成进来。

     1 namespace CAMCOCO.Model.Core.Entity
     2 {
     3     using System.Collections.Generic;
     4     using Validation;
     5 
     6     public partial class _BaseEntityValidation
     7     {
     8         private readonly List<IValidationRule> _validationRules;
     9         private ValidationHandler _validationHandler;
    10 
    11         protected _BaseEntityValidation()
    12         {
    13             _validationRules = new List<IValidationRule>();
    14             _validationHandler = new ValidationHandler();
    15         }
    16 
    17         public override void Dispose()
    18         {
    19             base.Dispose();
    20             _validationRules.Clear();
    21         }
    22 
    23         /// <summary>
    24         /// 为实体对象添加一条验证规则
    25         /// </summary>
    26         /// <param name="rule">验证规则</param>
    27         public void addValidationRule(IValidationRule rule)
    28         {
    29             if (rule != null)
    30             {
    31                 _validationRules.Add(rule);
    32             }
    33         }
    34 
    35         /// <summary>
    36         /// 对实体对象进行合法性验证,如果验证失败,将通过throw Exception进行抛出
    37         /// </summary>
    38         public void validate()
    39         {
    40             IValidationResultCollection results = getValidationResult();
    41             _validationHandler.handle(results);
    42         }
    43 
    44         private IValidationResultCollection getValidationResult()
    45         {
    46             IValidationResultCollection result = ValidationFactory.createValidationor().validate(this);
    47             foreach (var rule in _validationRules)
    48                 result.addResult(rule.validate());
    49             return result;
    50         }
    51 
    52 
    53 
    54     }
    55 }

    有了这个神器,在业务逻辑层里实现数据验证简直就是一种享受。

    下面是在业务层调用的时候的代码样子:

     1 public void addPopedomGroup(PopedomGroup obj)
     2         {
     3             try
     4             {
     5                 IRepository<PopedomGroup> res = createRepository<PopedomGroup>();
     6 
     7                 PopedomGroup dbObj = PopedomGroupFactory.createPopedomGroup();
     8                 dbObj.cloneFromWithProperties(obj, "Name", "IsHidden");
     9                 dbObj.Order.Index = createNewOrderIndex<PopedomGroup>();
    10 
    11                 dbObj.addValidationRule(new PopedomGroupCannotExistsSameNameRule(res, dbObj));
    12                 dbObj.validate();
    13                 res.add(dbObj);
    14                 commit();
    15             }
    16             catch (Exception ex)
    17             {
    18                 throw ex;
    19             }
    20         }
    dbObj.addValidationRule(new PopedomGroupCannotExistsSameNameRule(res, dbObj));

    这句代码可以很方便地在本次逻辑操作中加入任何的验证条件,而验证规则的编写也很简单,同时可以实现任意组合

    例如:

     1 namespace CAMCOCO.Business.Authentication.Rule
     2 {
     3     using System.ComponentModel.DataAnnotations;
     4     using CAMCOCO.Business.Core.Rule;
     5     using CAMCOCO.Model.Core.Validation;
     6     using CAMCOCO.Data;
     7     using CAMCOCO.Model.Authentication.Entity;
     8 
     9     public class PopedomGroupCannotExistsSameNameRule : BaseRule<PopedomGroup>
    10     {
    11         public PopedomGroupCannotExistsSameNameRule(IRepository<PopedomGroup> res, PopedomGroup checkObj)
    12             : base(res, checkObj)
    13         {
    14 
    15         }
    16 
    17         public override ValidationResult validate()
    18         {
    19             ValidationResult result = ValidationResult.Success;
    20             if (_res.exists(m => m.Id != _checkObj.Id && m.System.DeleteFlag == false && m.Name == _checkObj.Name))
    21             {
    22                 result = createValidationResult("PopedomGroup", "权限组名称不能重复");
    23             }
    24             return result;
    25         }
    26     }
    27 }

    OK,到此为止,老胡的实体模型基类基本就搭建完毕了,在老胡的架构里,所有的实体类都必须从三大基类(BaseEntityNormal, BaseEntityOrder, BaseEntityTree)派生而来,具备如下一些特性:

    1、所有的实体都有唯一的一个ID号。

    其实这个问题展开来还有一系列的考虑,在之前的项目经验中,我采用过两种形式的ID,一种是数据库自增标识,一种是Guid。两种方式分别都有自己的优点,自增标识属于数据库自主管理,我们写代码的时候不同进行维护,同时所有ID号都是连续的,优点是方便记忆,能够快速定位数据,够直观。同时缺点也是明显的,由于自增特性,我们没法手工任意修改,当需要做数据迁移或者在系统之间导入导出数据时,这个东西很麻烦,你得先建立一个临时表用于记录新老ID对应记录等等,同时因为其是连续的数字,如果在安全验证上出现漏洞,很容易就被用户调取到不属于自身范围的数据。而GUID正好解决以上两个问题,同时GUID带来的问题就是无法记忆无法推算,在开发及测试程序时无法很好地预判结果和肉眼查找数据。

    在老胡做这个架构的时候,两种方案都尝试了,最终为了保留EF中的某些重要特性,比如GUID模式通过EF无法自动生成符合老胡要求的主键,我希望数据的保存依托ID作为主键同时是一个聚集索引,但GUID明显不适合做聚集索引。手工制表的时候老胡一般都是吧GUID作为主键,然后去掉聚集索引,将聚集索引建立在数据创建时间字段上。

    2、所有实体都会记录下创建时间;

    3、所有实体都是逻辑删除;

    4、Order类实体可以通过框架标准接口进行排序;

    5、Tree类实体可以通过框架标准接口进行排序操作和节点操作;

    6、所有实体都具备完整的自我合法性验证功能;

    7、实体模型可以被业务层及以上的任意层使用,但以为除了业务层意外均不掌握修改实体的方法,所以实体数据的安全性得到了保障,要修改实体内容,只能通过业务层;

    8、通过EntityBuilder建造者来初始化实体基类信息,派生类中不用关心其基类部分的属性该如何赋值;

    BaseFilter的特性:

    1、凡是有查询需求的实体,都因为为其构造Filter,而这些Filter都必须派生自BaseFilter;

    2、BaseFilter中已经将实体基类中的标准属性进行了定义,派生类中只需要针对派生实体的特定属性进行特定扩展即可;

    3、Filter本身不应该有任何操作功能,只是一堆属性定义(和贫血实体一样);

    4、Filter的目的是取代查询函数里的一大堆参数而存在的

     1 //普通查询接口
     2 IQueryable<Entity> findEntityList(long id, string searchName, int maxThanAge, ...);
     3 
     4 //采用Filter模式
     5 class EntityFilter{
     6     public int Id{get;set;}
     7     public string searchName{get;set;}
     8     public int maxThanAge{get;set;}
     9     //...
    10 }
    11 
    12 IQueryable<Entity> findEntityList(EntityFilter filter);

    这是Model的第二篇,上一篇点这里

  • 相关阅读:
    【排序】题解_P1093奖学金
    简单了解连接服务器的要求
    centos7安装(纯文字版)
    JAVA虚拟机
    集合
    IO流
    反射
    多线程
    JAVA基础
    博客园皮肤文档
  • 原文地址:https://www.cnblogs.com/iambluebird/p/4970190.html
Copyright © 2020-2023  润新知