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这样的"大"方法。