Entity framework 如何在聚合根目录中更新子目录

Entity framework 如何在聚合根目录中更新子目录,entity-framework,oop,domain-driven-design,ef-code-first,aggregateroot,Entity Framework,Oop,Domain Driven Design,Ef Code First,Aggregateroot,我首先使用EF代码,然后延迟加载 我的问题涉及如何有效地更新孙子集合中的实体。首先,我担心这会在db中产生很多实际上并不需要的调用。但是,如果我的域类不关心持久性,我就看不到其他方法来做到这一点 以下是课程: public class Supplier { public int Id {get;set;} //...Supplier properties public virtual ICollection<Contract> Contracts {get;set

我首先使用EF代码,然后延迟加载

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

以下是课程:

  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;}
 }
我使用MVC使程序看起来像: 公共行动结果更新(交货合同变更DDC,int供应商ID)

首先,问题在于ChangeDeliveryContract。我一直没能让它工作。此外,我觉得像我这样通过集合进行查询可能效率低下。第三,映射30多个属性也感觉有点错误


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

好吧,这有点让人困惑,我把责任归咎于域模型和持久性模型的混合(是的,那些EF教程让大家都很困惑)。一个不应该影响另一个,这就是为什么您有存储库模式。是的,域不应该关心持久性

现在供应商已经不知道EF了,让我们看看。。。如果我理解正确,那么您非常需要重新设计供应商(可能还有子供应商),因为您需要考虑业务规则

对我来说,从代码中逆向设计需求是相当困难的,但我感觉供应商与不同的部门签订了交付合同。当您更改交付合同时,供应商应强制执行在该上下文中有效的业务规则(如果有多个上下文对同一实体有效,这一点很重要)

我认为尽管交付合同需要更多的澄清,因为我不能相信它只是一个只有30个属性的愚蠢对象。也许某些业务规则与某些属性有关?所以,我们需要更多的细节


另一方面,如果您真的需要映射30个属性br,因为事实就是这样,您可以使用Automapper进行映射。

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


请阅读Vaughn Vernon的一系列优秀文章,以深入探讨这个主题:.

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


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

感谢您的理解和耐心。是的,我觉得朝着Excel VBA=>硬编码SQL=>MVC和EF Code First=>DDD的方向发展是相当混乱的。我从中学到的例子把我弄糊涂了。除此之外,一个供应商和一家公司就一般条款、发票、rabates等创建一个或两个主合同。然后,每个供应商和部门就交货合同达成一致,包括交货日期、一周中每一天的订单截止日期(因此很快就会有很多财产)。DeliveryTerms受其中一个主合同中的条款管辖,业务规则是检查供应商和部门没有多个交货合同。还有一种行为是在合同变更时向部门发送信息,我没有包括在内。谢谢。所以我真的仔细阅读了这些文章(这是相当多的阅读),我详细地阅读了所有内容,我认为你的建议是有道理的。如果我从一致性的角度考虑这个案例,唯一的聚合契约的候选人就是契约(即,交付合同需要一个合同来管理它,如果没有它,它将是无用的——但是它具有身份,所以它不是一个价值类型)。然后,业务规则必须位于其自己的层或对象本身。感谢您的输入。据我所知,这里有几件事需要改变。首先,聚合根概念比我最初认为的要复杂一些,我试图使用关系强制执行的一些规则在域中混合了一些DB思想,应该使用实体方法中的业务逻辑强制执行。其次,正如您所指出的,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
 }
}
{
  var Supplier = supplierRepository.GetById(supplierid);
  supplier ChangeDeliveryContract (changedDc);
  supplierRepository.Save();

  //More code...
}