【问题标题】: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),所以我们有一个shiftdetail winter 坚持使用8 工作时间和shiftdetail summer 坚持6工作时间。现在我觉得非聚合根控制的班次细节不变量(worktime) 如何强制这个不变量?

  • 根据前面的信息,我是否犯了与聚合规范相关的错误?

【问题讨论】:

    标签: c# oop domain-driven-design aggregation aggregateroot


    【解决方案1】:

    非聚合根 (ShiftDetail) 是否可以保存另一个非聚合根 (WorkTime) 的引用?

    不,除非它们存在于同一个聚合中。

    您只能持有对其他聚合根 ID 的引用。

    您可能持有来自另一个聚合的嵌套实体 ID 的引用,但您应该注意,此 ID 是不透明的,您不能假设它的聚合根在内部如何使用它来查找嵌套实体。

    现在我觉得非聚合根(worktime)控制的班次细节不变量如何强制这个不变量?

    您可以通过两种方式强制执行不变量:

    1. 在聚合内。这意味着聚合必须足够大,它必须拥有它需要的所有状态。这种强制执行非常一致。

    2. 由 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 聚合上的静态方法
    猜你喜欢
    • 1970-01-01
    • 2013-05-31
    • 2018-11-08
    • 2018-08-12
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-04
    相关资源
    最近更新 更多