如何更新聚合根中的孙节点



I使用EF代码优先,并延迟加载。

我的问题涉及如何有效地更新孙集合中的实体。首先,我担心这会在数据库中进行很多不需要的调用。但是,如果我的领域类不关心持久性,我就看不到其他方法来做到这一点。

以下是类:

  public class Supplier
 {
  public int Id {get;set;}
  //...Supplier properties
  public virtual ICollection<Contract> Contracts {get;set;} 
  //supplier methods   
 }
 public class Contract
 {
  public int id {get;set;}
  public int SupplierId{get;set;}
  //---Contract properties
  [ForeignKey("SupplierId")]
  public virtual Supplier Supplier {get;set;}
  public virtual ICollection<DeliveryContract> DeliveryContracts {get;set;} 
 }
 public class DeliveryContract
 {
  public int Id {get;set;}
  public bool DeliveryOnMonday{get;set;}
  public bool DeliveryOnTuesday{get;set}
  //...30 different Delivery terms properties
  public Department Department {get;set;}
  public int ContractId {get;set;}
  [ForeignKey("ContractId")
  public virtual Contract Contract {get;set;}
 }

供应商是总根。所以我有一个关于供应商的方法,即ChangeDeliveryContract,这与现实世界中会发生的事情相对应。

public class Supplier
{
 //properties
 public void ChangeDeliveryContract (DeliveryContract cahangedDc)
 {
   //So from the supplier i have to find the contract to change
   var dcToUpdate = Contracts
                    .SingleOrDefault(c=>c.Id == changedDc.ContractId)
                    .SingleOrDefalut(dc=>dc.Id == changedDc.Id);
   //So... what do i do now? Map all 30 properties from changedDc to DcToUpdate
   //Some business rules is also applied here i.e. there can only be one
   // DeliveryContract between Supplier and Department
 }
}

我使用MVC,所以程序看起来像:public ActionResult Update(DeliveryContract changedDc,int supplierId)

{
  var Supplier = supplierRepository.GetById(supplierid);
  supplier ChangeDeliveryContract (changedDc);
  supplierRepository.Save();
  //More code...
}

首先,问题在于ChangeDeliveryContract。我没能让它发挥作用。此外,我觉得像我这样查询集合可能效率很低。第三,映射30多个属性也有点错误。

你们是怎么做到的,这里有最佳实践吗。

在应用DDD时,聚合根的选择可能会根据模型的各种特性而有所不同,其中包括关于子代数量等的考虑。在这种情况下,虽然供应商是AR,但并不意味着DeliveryContract也不能是AR。虽然供应商似乎是唯一的AR,所有关于供应商的操作都应该源于供应商类,但正如你所意识到的,这可能会在数据库调用方面变得难以控制AR的一个作用是保护不变量,而Supplier类中没有任何用于保护不变量的东西这可能表明Supplier不是实现所需业务规则的最合适的AR。因此,在我看来,在这种情况下,您可以将DeliveryContract作为AR,拥有自己的存储库和应用更改的方法。或者,您可以将Contract设置为AR,这取决于合同是否必须强制执行有关交付合同的任何不变量,也取决于对每个合同的预期交付合同数量的实际考虑。如果数量非常高,那么在合同类中收集交付合同是不切实际的。总的来说,我会选择更小的AR,尽管必须考虑不变量和一致性规则。

看看Vaughn Vernon的一系列文章,深入探讨这个主题:有效的骨料设计。

好吧,这有点令人困惑,我把它归咎于Domain和Persistence模型的混合(是的,那些EF教程在混淆所有人方面做得很好)。一个不应该影响另一个,这就是为什么您有存储库模式。是的,域不应该关心持久性。

既然主管已经不知道EF了,让我们看看。。。如果我理解正确,那么你非常需要重新设计供应商(可能还有儿童聚合),因为你需要考虑业务规则。

我很难从代码中对需求进行逆向工程,但我有一种感觉,供应商有向不同部门交付的合同。当您更改交货合同时,供应商应强制执行在该上下文中有效的业务规则(如果有多个上下文对同一实体有效,则这一点很重要)。

我认为交付合同需要更多的澄清,因为我不敢相信它只是一个只有30处房产的愚蠢物体。也许某些业务规则与某些属性有关?因此,我们需要更多的细节。

顺便说一句,如果你真的需要映射30个属性br因为就是这样,你可以使用Automapper。

关于ChangeDeliveryContract中的属性映射,您觉得映射30个属性有点错误。映射30个属性本身没有错。如果必须这样做,就必须这样做。您可以使用AutoMapper来简化任务。

我认为,如果你制作像"Supplier.MakeDeliveryOnMonday()"、"Supplier.DontMakeDeliveryOnTuesday())"这样的方法,代码的"感觉"可以改变。你可能可以猜测这些方法的作用(检查业务逻辑并将布尔值设置为true或false)。因此,您不必使用像ChangeDeliveryContract这样的"大"方法。

最新更新