基于DDD的.NET开发框架 - ABP的Entity设计思想
ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称。
ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应用程序的新起点,它旨在成为一个通用的WEB应用程序框架和项目模板。
ABP的官方网站:http://www.aspnetboilerplate.com
ABP官方文档:http://www.aspnetboilerplate.com/Pages/Documents
Github上的开源项目:https://github.com/aspnetboilerplate
一、基本概念
实体是DDD(领域驱动设计)的核心概念之一。Eirc Evans是这样描述的实体的:“它根本上不是通过属性定义的,而是通过一系列连续性和标识定义的”。因此,实体都有Id属性并且都存储到数据库中。一个实体一般会映射到数据库的一张表。
1、实体类
在ABP中,实体派生自Entity类,例如:
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。
2、接口约定
在很多应用程序中,很多实体具有像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默认会阻止),但是,对于激活或者未激活的实体,控制获取实体完全取决于你。
2、IEntity接口
实际上,Entity类实现了IEntity接口(且Entity实现了IEntity)。如果不想从Entity类中派生,那么可以直接实现这些接口。但是,除非你有一个好的原因不从Entity类派生,否则,不建议这么做。
二、ABP源码分析
代码:
部分类图:
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。
基于DDD的.NET开发框架 - ABP的Entity设计思想的更多相关文章
- 线上分享-- 基于DDD的.NET开发框架-ABP介绍
前言 为了能够帮助.Net开发者开拓视野,更好的把最新的技术应用到工作中,我在3月底受邀到如鹏网.net训练营直播间为各位学弟学妹们进行ABP框架的直播分享.同时为了让更多的.NET开发者了解ABP框 ...
- 基于DDD的.NET开发框架 - ABP启动配置
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 基于DDD的.NET开发框架 - ABP领域服务
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 基于DDD的.NET开发框架 - ABP初探
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 基于DDD的.NET开发框架 - ABP分层设计
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 基于DDD的.NET开发框架 - ABP仓储实现
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 基于DDD的.NET开发框架 - ABP依赖注入
返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...
- 基于DDD的.NET开发框架ABP实例,多租户 (Sass)应用程序,采用.NET MVC, Angularjs, EntityFramework-介绍
介绍 基于ABPZERO的多租户 (Sass)应用程序,采用ASP.NET MVC, Angularjs-介绍 ASP.NET Boilerplate作为应用程序框架. ASP.NET MVC和ASP ...
- 基于DDD的.NET开发框架ABP实例,多租户 (Saas)应用程序,采用.NET MVC, Angularjs, EntityFramework-介绍
介绍 基于ABPZERO的多租户 (Saas)应用程序,采用ASP.NET MVC, Angularjs-介绍 ASP.NET Boilerplate作为应用程序框架. ASP.NET MVC和ASP ...
随机推荐
- PHP 类型判断和NULL,空值检查
PHP是一种宽松类型的编程语言,在函数中对传入的参数值的“类型”以及”值是否为空或者NULL“进行检查是不可缺少的步骤. 类型检查 从PHP5开始,PHP允许对函数的参数进行类型约束,即可以约束参数的 ...
- MySQL 命令行工具之 mysqldump 深入研究
mysqldump 是MySQL的一个命令行工具,用于逻辑备份.可以将数据库和表的结构,以及表中的数据分别导出成:create database, create table, insert into的 ...
- 前端构建工具gulp介绍
2016年3月3日 10:46:08 晴 前端构建工具gulpjs的使用介绍及技巧 gulpjs是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也非常简 ...
- 烂泥:【解决】VMware Workstation中安装ESXI5.0双网卡问题
本文由秀依林枫提供友情赞助,首发于烂泥行天下. 由于需要做ESXI相关的实验,所以就在自己的机器上利用VM虚拟ESXI进行实验.因为此次实验是需要两块网卡的,所以就在创建ESXI虚拟机时添加了两块网卡 ...
- linux 目录结构及其相关命令
目录也是一个文件,它的唯一功能是用来保存文件及其相关信息.所有的文件,包括普通文件.设备文件和目录文件,都会被保存到目录中. 主目录 登录后,你所在的位置就是你的主目录(或登录目录),如果是root用 ...
- System V IPC(1)-消息队列
一.概述 System V三种IPC:消息队列,信号量,共享内存.这三种IPC最先出现在AT&am ...
- Shell命令行操作
1.1 shell提示符 [me@linuxbox ~]$ 如果最后一个字符是"#",表示当前终端会话有超级用户权限.使用root用户登录或者使用能提供超级用户权限的终端能获得该权 ...
- hihocoder #1388 : Periodic Signal NTT&FFT
传送门:hihocoder #1388 : Periodic Signal 先来几个大牛传送门: (模板) NTT long long 版 解法一:因为我们知道FFT会精度不够,所以坚持用NTT,但 ...
- Codeforces Round #283 Div.2 D Tennis Game --二分
题意: 两个人比赛,给出比赛序列,如果为1,说明这场1赢,为2则2赢,假如谁先赢 t 盘谁就胜这一轮,谁先赢 s 轮则赢得整个比赛.求有多少种 t 和 s 的分配方案并输出t,s. 解法: 因为要知道 ...
- 完全平方数(钟神的hao)
[问题描述] 从1− ?中找一些数乘起来使得答案是一个完全平方数,求这个完全平方数最大可能是多少. [输入格式] 第一行一个数字?. [输出格式] 一行一个整数代表答案对100000007取模之后的答 ...