返回ABP系列html
ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。git
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。github
ABP的官方网站:http://www.aspnetboilerplate.com数据库
ABP官方文档:http://www.aspnetboilerplate.com/Pages/Documents框架
Github上的开源项目:https://github.com/aspnetboilerplate函数
实体是DDD(领域驱动设计)的核心概念之一。Eirc Evans是这样描述的实体的:“它根本上不是经过属性定义的,而是经过一系列连续性和标识定义的”。所以,实体都有Id属性而且都存储到数据库中。一个实体通常会映射到数据库的一张表。源码分析
一、实体类网站
在ABP中,实体派生自Entity类,例如:ui
public class Person : Entity { public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person() { CreationTime = DateTime.Now; } }
上面定义了一个Person实体类,并且在Entity类中定义了一个Id属性,它是该Entity类的主键。所以,全部实体的主键名都是相同的,都是Id。编码
主键Id的类型是能够改变的,默认是int(int32)的。若是你想将Id定义为其余类型,能够像下面那样显示声明:
public class Person : Entity<long> { public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person() { CreationTime = DateTime.Now; } }
主键Id也能够设置为string,Guid或其余类型的。
Entity类重写了等号运算符(==),能够轻松地检查两个实体是否相同了(实体的Id相同则认为它们相同)。它也定义了IsTransient方法来检测它是否有Id。
二、接口约定
在不少应用程序中,不少实体具备像CreationTime的属性(数据库表也有该字段)用来指示该实体是何时被建立的。APB提供了一些有用的接口来实现这些相似的功能。也就是说,为这些实现了这些接口的实体,提供了一个通用的编码方式(通俗的说只要实现指定的接口就能实现指定的功能)。
1)、审计
实体类实现 IHasCreationTime 接口就能够具备CreationTime的属性。当该实体被插入到数据库时, ABP会自动设置该属性的值为当前时间。
public interface IHasCreationTime { DateTime CreationTime { get; set; } }
Person类能够经过实现IHasCreationTime接口来重写,以下:
public class Person : Entity<long>, IHasCreationTime { public virtual string Name { get; set; } public virtual DateTime CreationTime { get; set; } public Person() { CreationTime = DateTime.Now; } }
ICreationAudited经过增长了CreatorUserId扩展了IHasCreationTime:
public interface ICreationAudited : IHasCreationTime { long? CreatorUserId { get; set; } }
当保存一个新的实体时,ABP会自动地将当前的用户Id设置为CreatorUserId。
你也能够经过从CreationAuditedEntity类派生实体,从而轻易地实现ICreationAudited。
对于修改也有类似的接口:
public interface IModificationAudited { DateTime? LastModificationTime { get; set; } long? LastModifierUserId { get; set; } }
做为一个快捷方式,你能够从AuditedEntity类派生,而不须要直接实现IAudited。AuditedEntity类对于不一样类型的Id属性也有泛型的版本。
2)、软删除
软删除是一个通用的模式被用来标记一个已经被删除的实体,而不是实际从数据库中删除记录。例如:你可能不想从数据库中硬删除一条用户记录,由于它被许多其它的表所关联。为了实现软删除的目的咱们能够实现该接口 ISoftDelete:
public interface ISoftDelete{ bool IsDeleted { get; set; } }
ABP实现了开箱即用的软删除模式。当一个软删除实体被删除后,ABP检测到以后,会阻止删除,将IsDeleted设置为true并更新数据库中的实体。并且,它会自动地过滤数据库中软删除的实体,不会检索(select)它们。
若是你用了软删除,你有可能也想实现这个功能,就是记录谁删除了这个实体。要实现该功能你能够实现IDeletionAudited 接口,请看下面示例:
public interface IDeletionAudited : ISoftDelete { long? DeleterUserId { get; set; } DateTime? DeletionTime { get; set; } }
IDeletionAudited扩展了ISoftDelete,当删除一个实体时,ABP会自动设置这些属性。
若是你想为一个实体实现全部的审计接口(建立,修改和删除),那么能够直接实现IFullAudited,由于它继承了全部的这些接口:
public interface IFullAudited : IAudited, IDeletionAudited { }
做为一个快捷方式,你能够直接从FullAuditedEntity 类派生你的实体类,由于该类已经实现了IFullAudited接口。
注意:全部的审计接口和类都有一个定义导航属性到User实体的泛型版本(好比ICreationAudited和FullAuditedEntity<tprimarykey,tuser>)。
3)、激活/未激活
一些实体须要标记为激活的或未激活的。这样,你就能够根据实体的激活或者未激活状态来采起行动。你能够实现IPassivable接口来达到目的。该接口定义了IsActive属性。
若是实体在第一次建立时是激活的,那么你能够在构造函数中将IsActive设置为true。
这与软删除(IsDeleted)是不一样的。若是一个实体是软删除的,那么它就不会从数据库中检索到了(ABP默认会阻止),可是,对于激活或者未激活的实体,控制获取实体彻底取决于你。
二、IEntity接口
实际上,Entity类实现了IEntity接口(且Entity实现了IEntity)。若是不想从Entity类中派生,那么能够直接实现这些接口。可是,除非你有一个好的缘由不从Entity类派生,不然,不建议这么作。
代码:
部分类图:
IEntity<TPrimaryKey>: 封装了PrimaryKey:Id,这是一个泛型类型
IEntity: 封装了PrimaryKey:Id,这是一个int类型
Entity<TPrimaryKey> :支持主键是泛型类型的Entity
Entity:支持主键是int类型的Entity
IHasCreationTime: 封装了CreationTime
ICreationAudited: 封装了CreatorUserId,这个是long类型
CreationAuditedEntity<TPrimaryKey> : 支持主键是泛型类型的Entity,而且封装了CreationTime 和 CreatorUserId
CreationAuditedEntity: 只支持主键是int类型的Entity,而且封装了CreationTime 和 CreatorUserId
ICreationAudited<TUser> :封装了泛型类型的creator
CreationAuditedEntity<TPrimaryKey, TUser> : 支持主键是泛型类型,而且封装了泛型类型的creator的Entity
ISoftDelete:封装了软删除的标志IsDeleted
IHasDeletionTime:封装了DeletionTime
IDeletionAudited:封装了DeleterUserId,这个是long类型
IDeletionAudited: 封装了泛型类型的DeleterUser
IHasModificationTime:封装了LastModificationTime
IModificationAudited: 封装了LastModifierUserId,这个是long类型
IModificationAudited<TUser> : 封装了泛型类型的LastModifierUser
IAudited:从其父类接口那继承了Creation 和 Modification 的时间和UserID,这个是long类型
AuditedEntity<TPrimaryKey> :支持主键是泛型类型的Entity,而且从其父类接口那继承了Creation 和 Modification 的时间和UserID,这个是long类型
AuditedEntity: 与AuditedEntity<TPrimaryKey>的区别就是其只支持主键是int类型的Entity。
AuditedEntity<TPrimaryKey, TUser> :与AuditedEntity<TPrimaryKey>的区别就是其支持泛型类型的LastModifierUser和CreatorUser。
IAudited:从其父类接口那继承了Creation,Modification和delete 的时间和UserID,这个是long类型
FullAuditedEntity<TPrimaryKey> :支持主键是泛型类型的Entity,而且从其父类接口那继承了Creation,Modification和delete 的时间和UserID,这个是long类型
FullAuditedEntity:与FullAuditedEntity<TPrimaryKey>的区别就是其只支持主键是int类型的Entity
FullAuditedEntity<TPrimaryKey, TUser> :与FullAuditedEntity<TPrimaryKey>的区别就是其支持泛型类型的LastModifierUser,CreatorUser 和 deleteuser。