非聚合根可以持有另一个非聚合根的引用吗?
Posted
技术标签:
【中文标题】非聚合根可以持有另一个非聚合根的引用吗?【英文标题】:Can non aggregate-root hold a reference for another non aggregate-root? 【发布时间】:2019-02-13 12:46:25 【问题描述】:如果我有这样的two aggregates
:
第一个聚合:
WorktimeRegulation(根) 工作时间 法规注册数据说明:
工作时间规定:
public class WorkTimeRegulation : Entity<Guid>, IAggregateRoot
private WorkTimeRegulation()//COMB
: base(Provider.Sql.Create()) // required for EF
private WorkTimeRegulation(Guid id) : base(id)
_assignedWorkingTimes = new List<WorkingTime>();
_enrolledParties = new List<RegulationEnrolment>();
private readonly List<WorkingTime> _assignedWorkingTimes;
private readonly List<RegulationEnrolment> _enrolledParties;
public string Name get; private set;
public byte NumberOfAvailableRotations get; private set;
public bool IsActive get; private set;
public virtual IEnumerable<WorkingTime> AssignedWorkingTimes get => _assignedWorkingTimes;
public virtual IEnumerable<RegulationEnrolment> EnrolledParties get => _enrolledParties;
//...
Id| Name | NumberOfAvailableRotations| IsActive
1| General Rule | 2 | true
工作时间:
public class WorkTime : Entity<Guid>
private WorkTime()
: base(Provider.Sql.Create()) // required for EF
private WorkTime(Guid id) : base(id)
ActivatedWorkingTimes = new List<WorkingTimeActivation>();
private ICollection<WorkingTimeActivation> _activatedWorkingTimes;
public string Name get; set;
public byte NumberOfHours get; set;
public byte NumberOfShortDays get; set;
public Guid WorkTimeRegulationId get; private set;
public virtual ICollection<WorkingTimeActivation> ActivatedWorkingTimes get => _activatedWorkingTimes; private set => _activatedWorkingTimes = value;
//....
Id| Name | NumberOfHours| NumberOfShortDays |WorkTimeRegulationId
1 | Winter | 8 | 1 | 1
2 | Summer | 6 | 0 | 1
第二个聚合:
Shift(根) 班次详情 班次注册数据说明:
换档:
public class Shift : Entity<Guid>, IAggregateRoot
private readonly List<ShiftDetail> _assignedShiftDetails;
private readonly List<ShiftEnrolment> _enrolledParties;
public string Name get; set;
public ShiftType ShiftType get; set;
public int WorkTimeRegulationId get; set;
public bool IsDefault get; set;
public virtual WorkingTimeRegulation WorkTimeRegulation get; set;
public virtual IEnumerable<ShiftDetail> AssignedShiftDetails get => _assignedShiftDetails;
public virtual IEnumerable<ShiftEnrolment> EnrolledParties get => _enrolledParties;
//...........
Id| Name | ShiftType | WorkTimeRegulationId | IsDefault
1 | IT shift | Morning | 1 | 1
换档细节:
public class ShiftDetail : Entity<Guid>
public Guid ShiftId get; private set;
public Guid WorkTimeId get; private set;
public DateTimeRange ShiftTimeRange get; private set;
public TimeSpan GracePeriodStart get; private set;
public TimeSpan GracePeriodEnd get; private set;
public virtual WorkTime WorkTime get; private set;
private ShiftDetail()
: base(Provider.Sql.Create()) // required for EF
//..........
ShiftId WorkTimeId shift-start shift-end
1 1 08:00 16:00
1 2 08:00 14:00
我的问题在这里:
非聚合根 (ShiftDetail
) 可以持有引用吗
对于另一个非聚合根 (WorkTime
)?
领域专家澄清说:为了创建一个有效的转变,我们
应该有一个shift detail
对应于每个与
具体worktimeRegulation
。如果shiftDetails
中有引用,则无法更新worktime
中的工作时间数。前面的例子表明我们
有two worktimes(winter,summer)
,所以我们有一个shiftdetai
l
winter
坚持使用8
工作时间和shiftdetail
summer
坚持6
工作时间。现在我觉得非聚合根控制的班次细节不变量(worktime
) 如何强制这个不变量?
根据前面的信息,我是否犯了与聚合规范相关的错误?
【问题讨论】:
【参考方案1】:非聚合根 (ShiftDetail) 是否可以保存另一个非聚合根 (WorkTime) 的引用?
不,除非它们存在于同一个聚合中。
您只能持有对其他聚合根 ID 的引用。
您可能持有来自另一个聚合的嵌套实体 ID 的引用,但您应该注意,此 ID 是不透明的,您不能假设它的聚合根在内部如何使用它来查找嵌套实体。
现在我觉得非聚合根(worktime)控制的班次细节不变量如何强制这个不变量?
您可以通过两种方式强制执行不变量:
在聚合内。这意味着聚合必须足够大,它必须拥有它需要的所有状态。这种强制执行非常一致。
由 Saga/流程经理协调。该组件对可能的多个聚合内的更改做出反应,并将命令发送到其他聚合。 Saga 是 Aggregate 的对立面。这种执行最终是一致的。
【讨论】:
非常感谢您的回复,如果您能详细说明如何在我的具体情况下实现此功能,我将不胜感激。 @AnynameDonotcare 请详细说明您的不变量 首先对于与特定worktimeregulation
相关的每个WorkTime
实例我应该有一个ShiftDetail
,在我的例子中我有两个worktimes(winter,summer)
所以我应该有两个shiftdetails
一个用于winter
和一个summer
,其次ShiftTimeRange
shiftdetails
在工作时间应该等于NumberOfHours
在我的例子中winter
工作时间NumberOfHours = 8
所以ShiftTimeRange
= 08:00 to 16:00
- ->(16-8 = 8hours)
@AnynameDonotcare 从我看到的情况来看,您可以在工厂中强制执行以 worktimeRegulation 作为输入并返回 ShiftTimeRange 的不变量
@AnynameDonotcare 这个工厂可能是返回 Shift 实例的 Shift 聚合上的静态方法以上是关于非聚合根可以持有另一个非聚合根的引用吗?的主要内容,如果未能解决你的问题,请参考以下文章
基于ABP落地领域驱动设计-02.聚合和聚合根的最佳实践和原则