ABP框架 - 实体
本节内容:
实体是DDD一个核心的概念。Eric Evans是这么描述的:“一个对象根本上不是按它的特性定义的,而是按一个线程的连续性和身份来定义”。所以实体有一个id属性存入数据库中。一个实体通常映射成关系型数据库的一个表。
实体类
在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属性,它是这个实体的主键。所以所有的实体主键名都相同,都是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;
}
}
同样,你也可以把它设置成string,Guid或其它类型。
Entity类重写了equality操作符(==),用它可以非常容易地检查两个实体是否相等(它们的Id是否相等),同时也定义了IsTransient()方法检查实体是否有一个Id。
聚合根类
“聚合在DDD里是一个模式,一个DDD聚合是一个领域对象群,可由单独的单元创建。例如一个订单和它的项,这些可以是分离的对象,但把订单(和它的项一起)看成是一个单独的聚合是有好处的。“(Martin Fowler 查看完整描述)。
虽然ABP没有强迫你使用聚合,但你也可能想在你的应用里,创建聚合和聚合根。ABP扩展了Entity,定义了AggregateRoot类,为一个聚合创建聚合根实体。
领域事件
AggregateRoot定义了DomainEvents集合,通过聚合根对象产生领域事件。这些事件在当前工作单元完成前自动触发,实质上,任何实体都可以通过实现IGeneratesDomainEvents接口产生领域事件,但通常(最佳实践)在聚合根里产生领域事件,这就是为什么把它默认到AggregateRoot里,而不是Entity类里。
约定的接口
在很多应用里,有很多相似的实体属性(数据库表的字段),如表示实体何时创建的CreationTime,ABP提供了一些有用的接口,明确和展现这些通用属性,这也给实现这些接口的实体,在编写这些属性代码时提供了一种通用的方式。
审计
IHasCreationTime为一个实体的“创建时间”信息采用通用的属性,在一个实体插入到数据库前,ABP自动为实现了该接口的实体,设置CreationTime属性为当前时间。
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自动把CreatorUserId设置为当前用户的id。你也可以让你的类继承CreationAuditedEntity类实现ICreationAudited。它同时也有一个适用于不同类型Id属性的泛型版本。
也有一个类似的“修改”接口
public interface IHasModificationTime
{
DateTime? LastModificationTime { get; set; }
} public interface IModificationAudited : IHasModificationTime
{
long? LastModifierUserId { get; set; }
}
当更新一个实体时,ABP也自动设置这些属性。你只需要为你的类定义它们就可以。
如果你想实现所有审计属性,你可以直接实现IAudited接口:
public interface IAudited : ICreationAudited, IModificationAudited
{ }
更快捷的方式是:你可以继承AuditedEntity类来代替直接实现IAudited。AuditiedEntity类同样也有一个适用于不同类型Id属性的泛型版本。
注意:ABP从ABP会话里获取用户Id。
软删除
软删除是一个通用的模式,它把一个实体标记为“已删除”代替从数据库直接删除。例如,你不想把一个User从数据库硬删除,因为它可能与其它表有关联,ISoftDelete接口就是出于这种目的:
public interface ISoftDelete
{
bool IsDeleted { get; set; }
}
ABP实现了开箱即用模式的软删除模式。当一个软删除实体开始删除时,ABP检测它,阻止它被删除,设置IsDeleted为true,并把实体更新到数据库。同时,ABP不会从数据库获取(select)软删除的实体,会自动过滤它们。
如果你使用软删除,当软删除一个实体时,你可能也会想保存是谁删除和什么时候删除,你可以实现IDeletionAudited接口,如下所示:
public interface IDeletionAudited : ISoftDelete
{
long? DeleterUserId { get; set; } DateTime? DeletionTime { get; set; }
}
更快捷的方式是:你可以从已经实现了所有的FullAuditedEntity类继承你的实体。
- 注意1:所有审计接口和类都有一个为指向你的User实体的导航属性而设计的泛型版本(如ICreationAudited<TUser>和FullAuditedEntity<TPrimaryKey,TUser>)。
- 注意2:同时,它们都有一个AggregateRoot版本,如AuditedAggregateRoot。
活跃/消极 实体
有些实体需要标记为Active(活跃的)和Passive(消极的),然后你根据实体的活跃/消极状态进行不同的操作,IPassivable就是为此而设计的,它定义了IsActive属性。
如果你的实体想在创建时就是处于活跃状态,你可以在构造器里设置IsActive为true。
它与软删除(IsDeleted)不同,如果一个实体被软删除,Abp默认不从数据库里取出,但是是否获取活跃/消极实体完全取决于你。
实体变化事件
当一个实体插入、更新、删除时,ABP会自动触发某些事件,因此你可以注册这些事件执行你需要的任何逻辑。查看事件总线文档的“预定义事件”主题,获取更多信息。
IEntity 接口
实质上,Entity类实现了IEntity接口(且Entity<TPrimaryKey>实现了IEntity<TPrimaryKey>)。如果你不想从Entity类继承,你可以直接实现这些接口,这些接口对于其它实体类也是适用的,但是这不是推荐的方式,除非你有一个好的理由。
ABP框架 - 实体的更多相关文章
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- 一步一步使用ABP框架搭建正式项目系列教程
研究ABP框架好多天了,第一次看到这个框架的名称到现在已经很久了,但由于当时内功有限,看不太懂,所以就只是大概记住了ABP这个名字.最近几天,看到了园友@阳光铭睿的系列ABP教程,又点燃了我内心要研究 ...
- C#高级知识点&(ABP框架理论学习高级篇)——白金版
前言摘要 很早以前就有要写ABP高级系列教程的计划了,但是迟迟到现在这个高级理论系列才和大家见面.其实这篇博客很早就着手写了,只是楼主一直写写停停.看看下图,就知道这篇博客的生产日期了,谁知它的出厂日 ...
- 一步一步使用ABP框架搭建正式项目系列教程之本地化详解
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 本篇目录 扯扯本地化 ABP中的本地化 小结 扯扯本地化 本节来说说本地化,也有叫国际化.全球化的,不管怎么个叫法,反正道理都是一 ...
- ABP框架搭建项目系列教程基础版完结篇
返回总目录<一步一步使用ABP框架搭建正式项目系列教程> 经过前面十二篇的基础教程,现在终于该做个总结了. 回顾 第一篇,我们建议新手朋友们先通过ABP官网的启动模板生成解决方案,因为这样 ...
- 详解ABP框架的多租户
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ABP框架对多租户场景提供了很好的支持,内建了多租户的处理机制,今天我们来深入解析一下 ...
- [译]ABP框架使用AngularJs,ASP.NET MVC,Web API和EntityFramework构建N层架构的SPA应用程序
本文转自:http://www.skcode.cn/archives/281 本文演示ABP框架如何使用AngularJs,ASP.NET MVC,Web API 和EntityFramework构建 ...
- ABP框架详解(三)Domain
此处的Domain主要指Abp类库根目录下Domain文件夹.顾名思义该目录下是用来存放与领域实体,领域逻辑执行,存储,领域服务相关的内容. 1.Entities (1)为整个Abp框架后期开发的所有 ...
- AutoMapper在ABP框架中的使用说明
为了说明AutoMapper如何使用,我专门开设了一个专题来讲,如果您还没有查看该专题,请点击这里.既然系统地学习了AutoMapper,那么接下来就是该用它实战的时候了.今天,我们就来揭开AutoM ...
随机推荐
- 01.SQLServer性能优化之---水平分库扩展
汇总篇:http://www.cnblogs.com/dunitian/p/4822808.html#tsql 第一次引入文件组的概念:http://www.cnblogs.com/dunitian/ ...
- Springmvc数据校验
步骤一:导入四个jar包 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns=" ...
- AngularJS过滤器filter-保留小数,小数点-$filter
AngularJS 保留小数 默认是保留3位 固定的套路是 {{deom | number:4}} 意思就是保留小数点 的后四位 在渲染页面的时候 加入这儿个代码 用来精确浮点数,指定小数点 ...
- .Net多线程编程—预备知识
1 基本概念 共享内存的多核架构:一个单独的封装包内封装了多个互相连接的未处理器,且所有内核都可以访问主内存.共享内存的多核系统的一些微架构,例如内核暂停功能,超频. 内核暂停功能:当使用内核不多的时 ...
- 史上最详细git教程
题外话 虽然这个标题很惊悚,不过还是把你骗进来了,哈哈-各位看官不要着急,耐心往下看 Git是什么 Git是目前世界上最先进的分布式版本控制系统. SVN与Git的最主要的区别 SVN是集中式版本控制 ...
- BPM的魅力何在?
BPM(Business Process Management , 企业流程管理平台) 是带动企业流程自动化的帮 手,也是最能忠实反应出企业作业流程问题症结的系统工具,在管理上,BPM可以让管理者利用 ...
- 在UPDATE中更新TOP条数据以及UPDATE更新中使用ORDER BY
正常查询语句中TOP的运用: SELECT TOP 1000 * FROM MP_MemberGrade 随意更新一张表中满足条件的前N条数据: UPDATE TOP (1) MP_Member ...
- 续 CentOS7(mini) 运行MVC5 + Mariadb
上一篇,介绍了在CentOS7上使用mono官方二进制安装包快速安装mono环境 并且成功运行了一个Owin自宿主应用(Booker) 由于Owin自宿主应用不需要System.Web的支持,所以可以 ...
- FastClick 填坑及源码解析
最近产品妹子提出了一个体验issue —— 用 iOS 在手Q阅读书友交流区发表书评时,光标点击总是不好定位到正确的位置: 如上图,具体表现是较快点击时,光标总会跳到 textarea 内容的尾部.只 ...
- [PHP源码阅读]strtolower和strtoupper函数
字符串的操作函数中,字符串的大小写转换也算是比较常用的函数,其底层实现也比较简单,下面来一探究竟. 我在github上有对PHP源码更详细的注解.感兴趣的可以围观一下,给个star.PHP5.4源码注 ...