关于ABP聚合根类AggregateRoot的思考
AggregateRoot和Entity的区别
AggregateRoot继承于Entity,并实现了IGeneratesDomainEvents接口
public class AggregateRoot<TPrimaryKey> : Entity<TPrimaryKey>, IAggregateRoot<TPrimaryKey>, IEntity<TPrimaryKey>, IGeneratesDomainEvents
{
public AggregateRoot();
[NotMapped]
public virtual ICollection<IEventData> DomainEvents { get; }
}
在DDD里面聚合根是一定对应一个实体
为什么要使用AggregateRoot
实现了IGeneratesDomainEvents,属性DomainEvents可以方便产生领域事件,这些事件在当前的工作单元完成之前自动的触发。
在ABP里面不会强迫使用聚合,但既然选用了ABP这个框架,那就是希望能使用DDD的开发模式,所以使用AggregateRoot是更好的实践。
IGeneratesDomainEvents解析
先贴关键源码
public abstract class AbpDbContext : DbContext, ITransientDependency
{
public override int SaveChanges()
{
//从DomainEvents中拿到定义的领域事件
var changeReport = ApplyAbpConcepts();
var result = base.SaveChanges();
//数据保存后,触发领域事件
EntityChangeEventHelper.TriggerEvents(changeReport);
return result;
}
protected virtual EntityChangeReport ApplyAbpConcepts()
{
var changeReport = new EntityChangeReport();
...
var entries = ChangeTracker.Entries().ToList();
foreach (var entry in entries)
{
...
AddDomainEvents(changeReport.DomainEvents, entry.Entity);
}
return changeReport;
}
protected virtual void AddDomainEvents(List<DomainEventEntry> domainEvents, object entityAsObj)
{
var generatesDomainEventsEntity = entityAsObj as IGeneratesDomainEvents;
if (generatesDomainEventsEntity == null)
{
return;
}
if (generatesDomainEventsEntity.DomainEvents.IsNullOrEmpty())
{
return;
}
domainEvents.AddRange(generatesDomainEventsEntity.DomainEvents.Select(eventData => new DomainEventEntry(entityAsObj, eventData)));
//清空DomainEvents
generatesDomainEventsEntity.DomainEvents.Clear();
}
}
怎么在聚合根里面如何发布领域事件
DomainEvents.Add(new BlogUrlChangedEventData(this, oldUrl));
没有调用EventBus.Trigger来触发领域事件,那添加到DomainEvents的EventData是在什么时候触发的呢?
阅读下源码不难发现,重写了SaveChanges方法,在序列化到数据库后触发领域事件
聚合根里面有两个甚至多个方法都调用DomainEvents来产生领域事件,会不会造成事件多次触发呢?
不会,阅读源码,很容易发现DomainEvents只是负责临时传递EventData,传递给了changeReport这个局部变量后,就会清空,实际上真正触发领域事件的是changeReport。
简单说,就是每次调用SaveChanes后就会清空DomainEvents
关于ABP聚合根类AggregateRoot的思考的更多相关文章
- 基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则
目录 前言 聚合 聚合和聚合根原则 包含业务原则 单个单元原则 事务边界原则 可序列化原则 聚合和聚合根最佳实践 只通过ID引用其他聚合 用于 EF Core 和 关系型数据库 保持聚合根足够小 聚合 ...
- 基于ABP实现DDD--聚合和聚合根实践
在下面的例子中涉及Repository.Issue.Label.User这4个聚合根,接下来以Issue聚合为例进行分析,其中Issue聚合是由Issue[聚合根].Comment[实体].Iss ...
- Abp 领域事件简单实践 <四> 聚合根的领域事件
聚合根有个 DomainEvents 属性. 首先聚合根是一个实体.这个实体的仓储有变化(增删改)的时候,会触发这个DomainEvents 里的事件.就像EventBus.Trigger一样. pu ...
- DDD的实体、值对象、聚合根的基类和接口:设计与实现
1 前置阅读 在阅读本文章之前,你可以先阅读: 什么是DDD 2 实现值对象 值对象有两个主要特征:它们没有任何标识.它们是不可变的. 我们举个例子:小明是"浙江宁波"人,小红也是 ...
- 初识ABP vNext(11):聚合根、仓储、领域服务、应用服务、Blob存储
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 目录 前言 开始 聚合根 仓储 领域服务 BLOB存储 应用服务 单元测试 模块引用 最后 前言 在前两节中介绍了ABP模块开发的基本步 ...
- ASP.NET Core Web API下事件驱动型架构的实现(四):CQRS架构中聚合与聚合根的实现
在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅.通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件总线的实现.接下来对于事件驱动型架构的讨论,就需 ...
- 从壹开始微服务 [ DDD ] 之六 ║聚合 与 聚合根 (下)
前言 哈喽大家周二好,上次咱们说到了实体与值对象的简单知识,相信大家也是稍微有些了解,其实实体咱们平时用的很多了,基本可以和数据库表进行联系,只不过值对象可能不是很熟悉,值对象简单来说就是在DDD领域 ...
- NET Core Web API下事件驱动型架构CQRS架构中聚合与聚合根的实现
NET Core Web API下事件驱动型架构在前面两篇文章中,我详细介绍了基本事件系统的实现,包括事件派发和订阅.通过事件处理器执行上下文来解决对象生命周期问题,以及一个基于RabbitMQ的事件 ...
- Abp 聚合测试
Abp 官网开始的教程例子,是IRpositoty<entity> 直接出现在应用层.但是如果是一个聚合根也会这样吗? 那么聚合根是访问仓储的最小单元,要通过聚合根来操作业务,就是实体, ...
随机推荐
- PDFBox之文档创建
1.创建一个空的PDF 下面的小例子表示如何使用PDFBox来创建一个新的PDF文档. // 创建一个空的文档 PDDocument document = new PDDocument(); // 创 ...
- linuxsocket通信recv研究缓存机制
曾有过这样一个小疑问.当一个进程注册的插座后,,假设插座没有被调用recv函数接受包.能接受到数据包吗? 或者这样说,假设我的程序注冊了一个套接字去接受数据包,可是每收到一个数据包都须要非常长 ...
- OCP-1Z0-051-题目解析-第3题
3. You need to extract details of those products in the SALES table where the PROD_ID columncontains ...
- 使用sqlldr向Oracle导入大的文本(txt)文件
我们有多种方法可以向Oracle数据库里导入文本文件,但如果导入的文本文件过大,例如5G,10G的文本文件,有些方法就不尽如意了,例如PLSQL Developer中的导入文本功能,如果文本文件过大, ...
- 设计与实现的简单和经常使用的权限系统(五岁以下儿童):不维护节点的深度level,手工计算level,树形结构
以这种方式.和第三的类似介绍.所不同的是.深度未在数据库中存储节点level,添加和更改时间,护.而是,在程序中,实时去计算的. 至于后面的,依照level升序排序,再迭代全部的节点构造树,与第三篇 ...
- ASP.NET MVC之单元测试
ASP.NET MVC之单元测试分分钟的事2014-07-15 13:05 by 书洞里的猫, 550 阅读, 4 评论, 收藏, 编辑 一.为什么要进行单元测试? 大部分开发者都有个习惯(包括本人在 ...
- Oracle Database Instant Client 11g 32位和64位 安装包发布
Oracle Database Instant Client 11g 32位和64 Oracle Database Instant Client 11g 11.2.0.3.0 Instant Clie ...
- 第三方控件netadvantage UltraWebGrid总结
1.个人习惯前台绑定好实体字段,禁止自动生成:一些属性设置:AutoGenerateColumns="false" <igtbl:UltraWebGrid ID=" ...
- 创建自己的github代码库
前提: 1.安装git 2.在github上创建一个repository(库),如名字叫Hello-World,则git地址为https://github.com/username/Hello-Wor ...
- 代码阅读软件kscope源码安装指导
安装 kscope-1.6.2 1. ./configure --without-arts --prefix=/soft/kscope-1.6.2 (I customize the installi ...