我估计一片帖子写不完这个,慢慢来吧。。。
先上个图,按照图来说明应该容易说清楚一些。
在Model Core核心代码中,老胡创建了一个类 CAMCOCO.Model.Core,要求今后在Model Logic中编写的实体类都必须从这里继承。
Core里提供了两种基类,一个是Entity的基类,一个是Filter基类。
先给出实体类的继承结构:代码有点多,点开再看^v^
1 namespace CAMCOCO.Model.Core.Entity 2 { 3 using System; 4 5 #region _BaseEntity 数据实体基类 6 7 /// <summary> 8 /// 数据实体基类 9 /// </summary> 10 public abstract class _BaseEntity : IDisposable 11 { 12 //do nothing... 13 public virtual void Dispose() 14 { 15 } 16 } 17 18 #endregion 19 20 21 22 #region _BasicEnityClone 数据实体克隆类:继承自此的类均可实现Clone自身的操作 23 24 /// <summary> 25 /// 数据实体克隆类:继承自此的类均可实现Clone自身的操作 26 /// ---------------- 27 /// 本类为抽象类,不能直接实例化 28 /// </summary> 29 public abstract partial class _BasicEnityClone : _BaseEntity 30 { 31 //在分部类_BasicEnityClone中实现具体定义 32 } 33 34 #endregion 35 36 37 38 #region _BaseEntityValidation 数据实体自我验证类:继承自此的类可以进行数据合法性自我验证 39 40 /// <summary> 41 /// 数据实体自我验证类:继承自此的类可以进行数据合法性自我验证 42 /// </summary> 43 public abstract partial class _BaseEntityValidation : _BasicEnityClone 44 { 45 //在分部类_BaseEntityValidation中实现具体定义 46 } 47 48 #endregion 49 50 51 52 53 54 55 #region BaseEntityNormal 标准数据实体类:构成一个数据实体的基本属性 56 57 /// <summary> 58 /// 标准数据实体类:构成一个数据实体的基本属性 59 /// </summary> 60 public abstract partial class BaseEntityNormal : _BaseEntityValidation 61 { 62 //在分部类BaseEntityNormal中实现具体定义 63 } 64 65 #endregion 66 67 68 69 #region BaseEntityOrder 可自定义排序的数据实体类:通过增加OrderIndex属性实现自定义排序 70 71 /// <summary> 72 /// 可自定义排序的数据实体类:通过增加OrderIndex属性实现自定义排序 73 /// </summary> 74 public abstract partial class BaseEntityOrder : BaseEntityNormal 75 { 76 //在分部类BaseEntityOrder中实现具体定义 77 } 78 79 #endregion 80 81 82 83 #region BaseEntityTree 支持树形结构的数据实体类:通过增加ParentId属性实现树形结构 84 85 /// <summary> 86 /// 支持树形结构的数据实体类:通过增加ParentId属性实现树形结构 87 /// </summary> 88 public abstract partial class BaseEntityTree : BaseEntityOrder 89 { 90 //在分部类BaseEntityTree中实现具体定义 91 } 92 93 #endregion 94 95 }
简单说来就是 _BaseEntity -> _BasicEnityClone -> _BaseEntityValidation -> BaseEntityNormal -> BaseEntityOrder -> BaseEntityTree
_BasicEnityClone 虚类实现了实体间属性克隆的功能,这个在老胡的架构里很重要,在后面聚合方法的add和update里会说到为什么这么做。
_BaseEntityValidation 虚类则实现了实体模型的自我验证功能,一个实体对象数据是否合法(比如必填字段是否填写、数据库中是否存在同名记录等等),都是通过这个虚类中的代码来实现的。(下一节来说明这个东东了)
Entity基类就是所有实体的基类了,在以前的项目实践中,老胡总结出三种常见的数据(实体)模型来:
1、BaseEntityNormal模型:标准的数据模型,每条数据(每个实体)都具备一个唯一编号,也就是ID。在这之上,老胡又增加了几条标准,比如删除标记,比如记录时间。
1 namespace CAMCOCO.Model.Core.Entity 2 { 3 using System; 4 using System.ComponentModel.DataAnnotations; 5 using System.ComponentModel.DataAnnotations.Schema; 6 7 public partial class BaseEntityNormal 8 { 9 /// <summary> 10 /// 实体索引,在数据库中是一个自增标识,并且定义为主键,具备唯一性和聚集索引特性 11 /// </summary> 12 [Key] 13 public long Id { get; set; } 14 15 public class EntityNormalPropertyClass 16 { 17 18 19 /// <summary> 20 /// 实体创建时间,此时间作为数据创建的备案记录,在任何条件下均不允许修改 21 /// </summary> 22 [Required] 23 [Index(IsClustered = false, IsUnique = false)] 24 public DateTime GenerateTime { get; set; } 25 26 ///// <summary> 27 ///// 实体数据发布人索引,当无法明确数据来源时,这个属性可以设置为0 【老胡说事:这个东西已经被老胡无情地砍掉了,真没啥用!!】 28 ///// </summary> 29 //[Index(IsClustered = false, IsUnique = false)] 30 //public long OwnershipId { get; set; } 31 32 /// <summary> 33 /// 数据删除标志位,当为true时表示这是一条已删除数据 34 /// </summary> 35 [Index(IsClustered = false, IsUnique = false)] 36 public bool DeleteFlag { get; set; } 37 38 /// <summary> 39 /// 实体数据删除时间 40 /// </summary> 41 [Index(IsClustered = false, IsUnique = false)] 42 public DateTime DeleteTime { get; set; } 43 } 44 45 public EntityNormalPropertyClass System { get; set; } 46 } 47 }
2、BaseEntityOrder模型。在常见的系统设计中,有一类数据并非是根据ID来顺序或反序排列的,它们需要使用自定义排序,比如一个字典项。这类模型除了标准的实体属性外,应该还有一个自定义排序的Order_Index字段。
1 namespace CAMCOCO.Model.Core.Entity 2 { 3 using System; 4 using System.ComponentModel.DataAnnotations; 5 using System.ComponentModel.DataAnnotations.Schema; 6 7 8 public partial class BaseEntityOrder 9 { 10 public class EntityOrderPropertyClass 11 { 12 /// <summary> 13 /// 自定义排序时,数据的排序序号,可根据此来进行ASC或DESC的排序 14 /// </summary> 15 [Index(IsClustered = false, IsUnique = false)] 16 public int Index { get; set; } 17 } 18 public EntityOrderPropertyClass Order { get; set; } 19 } 20 }
3、BaseEntityTree模型。还有一种模式的数据格式也是很常见的,就是树形模型。例如我们在做组织架构时、商品类目时,就肯定会用到这种模型了。老胡也把这种模型给定义出来了,增加了个ParentId的属性。
1 namespace CAMCOCO.Model.Core.Entity 2 { 3 using System; 4 using System.ComponentModel.DataAnnotations; 5 using System.ComponentModel.DataAnnotations.Schema; 6 7 public partial class BaseEntityTree 8 { 9 public class EntityTreePropertyClass 10 { 11 /// <summary> 12 /// 实体数据的父节点索引,在Tree模型或父子关系模型中,用于表现层级结构的属性 13 /// </summary> 14 [Index(IsClustered = false, IsUnique = false)] 15 public long ParentId { get; set; } 16 } 17 18 public EntityTreePropertyClass Tree { get; set; } 19 } 20 }
额,有了这三种基本模型,绝大部分格式的数据结构咱都能满足了,当然出了更特殊的数据结构的时候,如果有必要,我们再来增加一种就好了。
为什么要把这三种模型作为标准提出来呢?因为老胡的架构想实现一个功能,那就是,只要你是BaseEntityOrder派生出来的,那老胡的架构自身就能提供标准的移动接口来管理数据的上移、下移、置顶、置尾功能了,不用你再去写代码(到处写实现相同功能的代码一直是老胡深恶痛绝的)。
至于怎么实现这个东东?在后面的Business Core里会说到的。
再说说BaseFilter基类吧,因为在UI层会用到两个很重要的东西,一个是实体类的定义,比如在界面上显示一个客户资料时,我们一般这样做:
Customer cus = iCustomerQuery.findCustomer(customerId);
cus.Name...
cus.Address...
我们在使用Customer时,必须有这个实体类的原型定义,SO,实体模型必须暴露给UI层使用。
为什么业务层又可以不暴露给UI层呢,因为老胡在中间加了个SOA层,业务层是暴露给SOA的,UI对业务的操作是通过SOA来进行的,所以不强制要求UI知道业务层。
当UI需要查找某些数据时,老胡希望有一个尽量规范的格式来进行查询交互,所以引入了Filter这个概念。UI将需要的查询条件构造为一个符合要求的Filter,然后交给SOA,由SOA转发给Business,业务层就清楚需要查询什么样的数据了。
so,,,,Filter是什么?Filter就是在老胡架构中用于描述筛选条件的一个特殊类,目的是用来减少函数调用(如findXXXXList())中的参数个数的!
1 namespace CAMCOCO.Model.Core.Filter 2 { 3 using CAMCOCO.Common.CommonTypeDefine.CommunicationProtocol; 4 5 public abstract class BaseFilter 6 { 7 public DataPaging PageInfo { get; set; } 8 public string[] OrderName { get; set; } 9 public bool[] IsAsc { get; set; } 10 11 /// <summary> 12 /// 支持IdList模式 13 /// </summary> 14 public string Id { get; set; } 15 public bool DeleteFlag { get; set; } 16 /// <summary> 17 /// 具体时间 18 /// </summary> 19 public string GenerateTime { get; set; } 20 /// <summary> 21 /// 时间段-开始 22 /// </summary> 23 public string GenerateTime_start { get; set; } 24 /// <summary> 25 /// 时间段-结束 26 /// </summary> 27 public string GenerateTime_end { get; set; } 28 public string DeleteTime { get; set; } 29 public string DeleteTime_start { get; set; } 30 public string DeleteTime_end { get; set; } 31 32 public string MutiSearchKeywords { get; set; } 33 34 public BaseFilter() 35 { 36 PageInfo = new DataPaging() { PageIndex = 1, PageSize = 30, TotalCount = 0, PageCount = 0, }; 37 OrderName = new string[] { "Id" }; 38 IsAsc = new bool[] { false }; 39 40 Id = ""; 41 DeleteFlag = false; 42 GenerateTime = ""; 43 GenerateTime_start = ""; 44 GenerateTime_end = ""; 45 DeleteTime = ""; 46 DeleteTime_start = ""; 47 DeleteTime_end = ""; 48 49 MutiSearchKeywords = ""; 50 } 51 } 52 }
可以看到,在老胡的架构中,凡是有查询数据的时候都可以通过Filter构造一些标准的查询条件,这里包括页面尺寸信息(每页多少条数据、第几页、数据库中一共多少条符合条件的数据、有多少页),删除标记,数据生成时间(范围),数据删除时间(范围),甚至可以进行关键字模糊查询(MutiSearchKeywords)。
每个具体的实体模型自身还具备什么特殊的查询条件?OK,从BaseFilter派生出去,做一个新的EntityFilter就搞定了。
GO ON....待续