• [CAMCOCO][C#]我的系统架构.服务器端.(三)----Model层


    我估计一片帖子写不完这个,慢慢来吧。。。

    先上个图,按照图来说明应该容易说清楚一些。

    在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 }
    View Code

    简单说来就是 _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....待续

  • 相关阅读:
    本周工作量统计
    第15周个人作业
    16周第一组作业
    排球比赛积分规则
    典型用户和场景
    我和计算机
    第18周冲刺
    16周个人作业
    Java中动态获取项目根目录的绝对路径
    Spring框架下类的初始化顺序
  • 原文地址:https://www.cnblogs.com/iambluebird/p/4969431.html
Copyright © 2020-2023  润新知