Asp.net mvc 如何使用EF实现聚合根存储库添加子实体

Asp.net mvc 如何使用EF实现聚合根存储库添加子实体,asp.net-mvc,entity-framework,domain-driven-design,repository-pattern,aggregateroot,Asp.net Mvc,Entity Framework,Domain Driven Design,Repository Pattern,Aggregateroot,我正在开发一个MVC应用程序。我有一个域模型,我首先使用存储模式进行数据访问和实体框架代码。我还有一个UnitOfWork类,我通过它调用存储库操作 我的问题主要出现在我试图利用聚合根并通过其父存储库处理子对象时 这就是问题所在: 父类“供应商”与部门有多个合同。在这种情况下,我选择将合同作为供应商的子项 要添加新合同,我需要添加一个方法来在我的SupplierRepository中添加合同,我尝试了: public class SupplierRepository : GenericRepo

我正在开发一个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);

            }
当我打电话时

_unitOfWork.save();
我得到一个错误,告诉我:

一个实体对象不能被多个IEntityChangeTracker实例引用

UnitOfWork实例化my DbContext(myDbContext)和MySupplierRepository,并调用myDbContext.Save()

  • 为什么我会有这种行为
  • 我应该如何实现聚合根存储库(子对象的CRUD操作)
  • 据我所知,我应该在存储库中有一个方法来获取合同并添加它,而不是在我的MVC应用程序的控制器中这样做,但我似乎无法让它工作

    我已经看到了很多关于聚合根的信息,但是没有关于如何实现它的示例

    谢谢

    解决方案:

    我终于明白了

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

    希望有人能通过阅读这篇文章来节省时间

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

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

    并调用UnitOfWork.Save()方法。

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

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

    这实际上是UnitOfWork背后的ide,它们使用相同的上下文。不知何故,通过尝试在其父存储库中添加一个子存储库,它似乎创建了一个新的上下文。。。也就是说,我的存储库从我的UnitOfWork类获取上下文,因此它只实例化一个上下文并将其保留,直到它被释放为止(UnitOfWork实现IDisposable)。公开它的唯一原因是我需要保存合同信息(折扣、交付费等)添加到数据库,以便控制器从表单获取输入,并通过调用_unitOfWork.SupplierRepository.AddSupplierContract(contractToAdd)将其保存。你可能是正确的结构思维虽然,但我仍然认为供应商作为一个提供合同,因此作为根。我不知道我还能怎么做?如果供应商聚合将其添加到内部集合中的applier.AddContract(contractToAdd)如何。当为供应商调用save时,它应通过可访问性保持添加的合同。对于另一种方法,请看这里:嗯,我想这似乎是一个更好的解决方案,同时也给了供应商一些行为。然后,由SupplierRepository管理的聚合根将只保留供应商的状态。然后我获取当前供应商(mySupplier),调用mySupplier.AddContract(contractToAdd),然后调用_unitOfWork.SupplierRepository.Update(mySupplier)并保存?听起来是个更好的解决方案。。。
    kernel.Bind<MyContext>().ToSelf().InRequestScope();