我正在开发一个MVC应用程序。我有一个域模型,我使用repositry模式进行数据访问和Entity Framework Code First。我还有一个UnitOfWork类,我通过它调用存储库操作。
当我尝试利用聚合根并通过父存储库处理子对象时,我的问题主要出现了。
这是问题所在: 父类“供应商”与部门有多个合同。在这种情况下,我选择让合同成为供应商的子女。
要添加新合约,我需要添加一个方法来在我的SupplierRepository中添加合约,我试过:
public class SupplierRepository : GenericRepository<Supplier>
{
public SupplierRepository(MyContext context)
: base(context)
{
}
public void AddSupplierContract(SupplierContract contract)
{
var supplier = context.Suppliers.Find(contract.SupplierId);
supplier.Contract.Add(contract);
}
我也尝试过:
public void AddSupplierContract(SupplierContract contract)
{
context.Entry(contract).State = EntityState.Added;
}
}
当我打电话
_unitOfWork.save();
我收到错误告诉我:
IEntityChangeTracker的多个实例
无法引用实体对象
UnitOfWork实现我的DbContext(myDbContext)和我的SupplierRepository并调用myDbContext.Save()
据我所知,我应该在存储库中有一个方法来获取合同并添加它,而不是在我的MVC应用程序的Controller中执行此操作,但我似乎没有让它工作。
我已经看到了很多关于聚合根的信息,但没有关于如何实现它的例子。
感谢。
解决方案:
好吧,我终于明白了。
因此,存储库不存在问题,但新的SupplierContract向商店查询了创建它的用户实体(通过扩展方法)。显然这个上下文没有处理,因此当我实现它以保存合同实体时,我有两个当前的DbContexts。
希望有人通过阅读本文来节省时间。
我通过在SupplierRepository中这样做解决的聚合根存储库:
public void AddSupplierContract(SupplierContract contract)
{
db.SupplierContracts.Add(contract);
}
并调用UnitOfWork.Save()方法。
答案 0 :(得分:1)
虽然从技术上讲你可能已经解决了这个问题,但我希望你知道你的设计中存在一些根本性的缺陷(除非你使用Fowler存储库):存储库(DDD类)处理聚合只要。需要将SupplierContract添加到上下文中的事实不是调用代码的关注点。那么,为什么要暴露这种方法?我还会重新考虑让存储库委派保存(为什么还有一个UoW)。就聚合物而言,我感觉你似乎将它们视为结构对象,而不是行为对象。因此,你似乎陷入了痛苦的世界,经历了一些动作,但没有获得任何价值。
答案 1 :(得分:0)
要消除该错误,您应该使用相同的MyContext
实例来创建所有存储库。如果使用某个dependency-injector,它应该允许您通过单个请求配置相同的MyContext对象。例如,对于Ninject,那将是
kernel.Bind<MyContext>().ToSelf().InRequestScope();