-1

我首先使用 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+属性也感觉有点不对劲。

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

4

3 回答 3

1

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

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

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

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

另一方面,如果您确实需要映射 30 个属性,因为它就是这样,您可以使用 Automapper。

于 2012-03-02T15:10:23.143 回答
1

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

查看 Vaughn Vernon 的一系列精彩文章,深入探讨这个主题:有效的聚合设计

于 2012-03-03T01:42:25.727 回答
1

关于ChangeDeliveryContract中的属性映射,你觉得映射30个属性有点不对劲。映射 30 个属性本身并没有错。如果必须完成,就必须完成。您可以使用 AutoMapper 来简化任务。

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

于 2012-03-27T09:59:13.880 回答