0

我正在开发一个 MVC 应用程序。我有一个域模型,我使用存储库模式进行数据访问和实体框架代码优先。我还有一个 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()

  1. 为什么我会出现这种行为
  2. 我应该如何实现聚合根存储库(子对象的 CRUD 操作)

据我了解,我应该在存储库中有一个方法来接受合同并添加它,而不是在我的 MVC 应用程序的控制器中执行此操作,但我似乎没有让它工作。

我看过很多关于聚合根的信息,但没有关于如何实现它的示例。

谢谢。

解决方案:

好吧,我终于想通了。

所以这不是存储库的问题,但是新的 SupplierContract 向存储库查询创建它的用户实体(通过扩展方法)。显然这个上下文没有处理,因此当我实例化它以保存合同实体时,我有两个当前的 DbContexts。

希望有人通过阅读本文来节省时间。

我通过在 SupplierRepository 中这样做解决了聚合根存储库:

    public void AddSupplierContract(SupplierContract contract)
    {
        db.SupplierContracts.Add(contract);
    }

并调用 UnitOfWork.Save() 方法。

4

2 回答 2

1

虽然从技术上讲您可能已经解决了这个问题,但我确实希望您知道您的设计中存在一些根本性的缺陷(除非您使用 Fowler 存储库):存储库(DDD 类型)仅处理聚合。需要将 SupplierContract 添加到上下文中的事实与调用代码无关。那么,为什么要公开该方法?我还会重新考虑让存储库委托保存(为什么还有 UoW)。就聚合而言,我感觉您似乎将它们视为结构对象,而不是行为对象。因此,您似乎进入了一个痛苦的世界,经历了一些动作,但没有得到任何价值。

于 2012-02-13T22:24:01.743 回答
0

要消除该错误,您应该使用相同MyContext的实例来创建所有存储库。如果您使用一些依赖注入器,它应该允许您通过单个请求配置相同的 MyContext 对象。例如,对于 Ninject,这将是

kernel.Bind<MyContext>().ToSelf().InRequestScope();
于 2012-02-13T16:38:50.713 回答