Domanda

I'm developing an MVC application. I have a Domain Model, and I use a repositry pattern for data access and Entity Framework Code First. I also have a UnitOfWork class which I call the repository operations through.

My problem mainly arises when I try to take advantage of aggregate roots and handle child objects through their parent repository.

This is the problem: Parent class "Supplier" has several Contracts with Departments. I've chosen to make the contract a child of Supplier in this case.

To add a new contract I need to add a method to add a contract in my SupplierRepository, I tried:

 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);

            }

And I also tried:

            public void AddSupplierContract(SupplierContract contract)
            {
                context.Entry(contract).State = EntityState.Added;
            }

         }

When i call

_unitOfWork.save();

I get an error telling me:

An entity object cannot be referenced by multiple instances of IEntityChangeTracker

UnitOfWork instansiates my DbContext (myDbContext) and my SupplierRepository and calls the myDbContext.Save()

  1. Why do I get this behavior
  2. How should I implement an Aggregate Root Repository (CRUD operations for the child objects)

As far as I understand I should have a method in the repository that takes a contract and adds it, and not do this in the Controller of my MVC app, but I don't seem to get it working.

I've seen a lot of information about Aggregate Roots, but no examples of how to implement it.

Thanks.

Solution:

Well I finally figured it out.

So it was not a problem with the repository, but the new SupplierContract queryed the store for the user entity that created it (through an extension method). Obviously this context did not dispose and therefore i had two current DbContexts when I instansiated it to save the contract entity.

Hopefully someone saves time by reading this.

The Aggregate Root repository I solved by just doing like this in the SupplierRepository:

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

And calling UnitOfWork.Save() method.

È stato utile?

Soluzione

While technically you may have solved this issue, I do hope you are aware there's something fundamentally flawed in your design (unless you're using Fowler repositories): repositories (the DDD kind) deal in aggregates only. The fact that SupplierContract needs to be added to the context is not a concern of the calling code. So, why expose that method? I would also reconsider having the repository delegate the save (why else have a UoW). As far as aggregates are concerned I get the feeling you seem to be treating them as structural objects, not as behavioral ones. Hence you seem to be in for a world of pain, going through some of the moves, but not getting any of the value.

Altri suggerimenti

To get rid of that error, you should use same MyContext instance to create all the repositories. If you use some dependency-injector, it should allow you to configure same MyContext object through single request. For example, for Ninject, that would be

kernel.Bind<MyContext>().ToSelf().InRequestScope();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top