基于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 ...
随机推荐
- 十五天精通WCF——第六天 你必须要了解的3种通信模式
wcf已经说到第六天了,居然还没有说到这玩意有几种通信模式,惭愧惭愧,不过很简单啦,单向,请求-响应,双工模式,其中的第二种“请求-响应“ 模式,这个大家不用动脑子都清楚,这一篇我大概来分析下. 一: ...
- 【转载】CentOS 6.3下rsync服务器的安装与配置
一.rsync 简介 Rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件,也可以使用 Rsync 同步本地硬盘中的不同目录. Rsy ...
- Filestream 使用简单步骤
为了减少大文件在数据库的存储对数据库的读写效率造成的压力,多了FileStream这一个功能,下面介绍一下如何快速使用FileStream. 1.开启SqlServer实例对FileStream 的开 ...
- Kafka三款监控工具比较(转)
在之前的博客中,介绍了Kafka Web Console这 个监控工具,在生产环境中使用,运行一段时间后,发现该工具会和Kafka生产者.消费者.ZooKeeper建立大量连接,从而导致网络阻塞.并且 ...
- C语言怎么将用户账号密码写入文件实现登录注册功能?
创建储存用户账号密码的文件: void Create_File() { FILE *fp; if ((fp = fopen("users.txt","rb")) ...
- 说说React
一个组件,有自己的结构,有自己的逻辑,有自己的样式,会依赖一些资源,会依赖某些其他组件.比如日常写一个组件,比较常规的方式: 通过前端模板引擎定义结构 JS文件中写自己的逻辑 CSS中写组件的样式 通 ...
- [转]六款值得推荐的android(安卓)开源框架简介
本文转自:http://www.jb51.net/article/51052.htm .volley 项目地址 https://github.com/smanikandan14/Volley-demo ...
- Codeforces Round #282 Div.1 B Obsessive String --DP
题意: 给两个串S,T,问能找出多少的S的(a1,b1)(a2,b2)..(ak,bk),使Sa1---Sb1,...Sak---Sbk都包含子串T,其中k>=1,且(a1,b1)...(ak, ...
- qau-国庆七天乐——A
A - Who's in the Middle //先吐槽一波vj,不知道怎么回事,bits/stdc++.h不能用了...坑爹 7225007 upstar A Compile Error ...
- java 24 - 11 GUI之制作登陆注册页面
简单说说,懒得发了... 步骤: A:首先写出登陆注册需要用到类以及代码(IO流) B:然后创建登陆窗口和注册窗口 C:各个监听事件: a:登录窗口 1.重置:把2个文本框的内容全部清空 2.注册:关 ...