關於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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM