0

我正在开发一个MVC应用程序。我有一个领域模型,我使用数据访问和实体框架代码优先的存储模式。我还有一个UnitOfWork类,我称之为存储库操作。如何实现聚合根存储库添加与EF的子实体

我的问题主要出现在我尝试利用聚合根并通过其父存储库处理子对象时。

这就是问题: 父类“供应商”有几个与部门的合同。在这种情况下,我选择将合同作为供应商的子女。

要添加新的合同,我需要添加一个方法来在我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 instansiates我的DbContext(myDbContext)和我SupplierRepository并调用myDbContext.Save()

  1. 我为什么会这样行为
  2. 我应该怎样实现一个聚合根库(CRUD操作的子对象)

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

我见过很多关于Aggregate Roots的信息,但没有看到如何实现它的例子。

谢谢。

解决方案:

嗯,我终于想通了。

所以这是不与存储库中的问题,但新的SupplierContract queryed用于创建它的用户实体店铺(通过扩展方法)。很明显,这个上下文没有处理,因此当我为了保存合同实体而进行实例化时,我有两个当前的DbContext。

希望有人通过阅读这节省了时间。

的聚合根库由我只是在做这样的SupplierRepository解决:

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

,并呼吁UnitOfWork.Save()方法。

回答

1

虽然在技术上可能已经解决了这个问题,我希望大家都知道有一些根本性的缺陷,在您的设计(除非你使用福勒库):仓库( DDD类)只处理总量。 SupplierContract需要添加到上下文的事实并不是调用代码的关注点。那么,为什么要揭露这种方法?我也会重新考虑让存储库委托保存(为什么还有一个UoW)。就聚合物而言,我觉得你似乎将它们视为结构对象,而不是行为的对象。因此,你似乎处于一个痛苦的世界,经历了一些动作,但没有获得任何价值。

+0

那么,揭露它的唯一原因是我需要将合同信息(折扣,交付费等)保存到数据库,以便控制器从表单中获取输入并通过调用_unitOfWork.SupplierRepository.AddSupplierContract(contractToAdd )。尽管你可能对结构思想是正确的,但我仍然认为供应商是提供合同的供应商,因此也是根源。我不知道我会怎么做呢? – cfs 2012-02-13 23:53:45

+0

aSupplier.AddContract(contractToAdd)供应商汇总将其添加到内部集合中的情况。当为供应商调用保存时,它应该按照可达性添加合同。对于另一种方法,看这里:http://stackoverflow.com/questions/8556365/ef-4-2-code-first-and-ddd-design-concerns/8560328#8560328 – 2012-02-14 09:39:38

+1

嗯,我想这似乎是一个更好的解决方案,并给供应商一些行为。然后由供应商库管理的聚合根将只持续供应商的状态。所以我然后获取当前供应商(mySupplier),调用mySupplier.AddContract(contractToAdd),然后我调用_unitOfWork.SupplierRepository.Update(mySupplier)并保存?听起来像更好的解决方案... – cfs 2012-02-14 11:19:54

0

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

kernel.Bind<MyContext>().ToSelf().InRequestScope(); 
+0

这实际上是UnitOfWork背后的ide,它们使用相同的上下文。不知何故,通过试图在它的父库中添加一个子项,它似乎创建了一个新的上下文......也就是说,我的存储库从我的UnitOfWork类获取上下文,所以它只会创建一个上下文,并保留它直到它被丢弃(UnitOfWork实现IDisposable)。 – cfs 2012-02-13 16:49:08