"Multiple instances of IEntityChangeTracker cannot relate to the same entity object."

asp.net asp.net-mvc asp.net-mvc-3 c# entity-framework

Question

I have 3 database tables: Vendors, Regions, and VendorRegions:

Vendors
-------------------
VendorID (PK)
Name

Regions
-------------------
RegionID (PK)
Name

VendorRegions
-------------------
VendorID (PK)
RegionID (PK)

On my page to create a vendor, I list out every Region in a checkbox list. For every region that is checked, I'd like to add the VendorID and RegionID to the VendorRegions table.

I'm using Entity Framework, C# and MVC 3.

Here's my controller code:

public class VendorsController : Controller
{
    readonly IVendorsRepository _vendorsRepository;
    readonly IRegionsRepository _regionsRepository;

    public VendorsController()
    {
        _vendorsRepository = new SqlVendorsRepository();
        _regionsRepository = new SqlRegionsRepository();
    }

    [HttpPost]
    public ActionResult Create(VendorViewModel viewModel, string[] Regions)
    {
        var vendor = new Vendor();
        TryUpdateModel(vendor);

        if (ModelState.IsValid)
        {
            vendor.Regions.Clear();
            foreach (var regionId in Regions)
            {
                vendor.Regions.Add(_regionsRepository.GetRegion(Int32.Parse(regionId)));
            }

            _vendorsRepository.SaveVendor(vendor);
            return RedirectToAction("Index");
        }

        return View(viewModel);     // validation error, so redisplay same view
    }
}

Here's my Vendors repository code:

public class SqlVendorsRepository : IVendorsRepository
{
    private readonly MyDBEntities _entities;

    public SqlVendorsRepository()
    {            
        _entities = new MyDBEntities();
    }


    public void SaveVendor(Vendor vendor)
    {
        // If it's a new vendor, just attach it to the DataContext
        if (vendor.VendorID == 0)
            _entities.Vendors.Context.AddObject("Vendors", vendor); // ERROR HERE
        else if (vendor.EntityState == EntityState.Detached)
        {
            // We're updating an existing vendor, but it's not attached to this data context, so attach it and detect the changes
            _entities.Vendors.Context.Attach(vendor);
            _entities.Vendors.Context.Refresh(System.Data.Objects.RefreshMode.ClientWins, vendor);
        }
        _entities.Vendors.Context.SaveChanges();
    }
}

The error occurs when I try to save my vendor, at _entities.Vendors.Context.AddObject("Vendors", vendor);. And just in case, here's my Regions repository code:

public class SqlRegionsRepository : IRegionsRepository
{
    private readonly MyDBEntities _entities;

    public SqlRegionsRepository()
    {            
        _entities = new MyDBEntities();
    }


    public IQueryable<Region> Regions
    {
        get { return _entities.Regions.AsQueryable(); }
    }


    public Region GetRegion(int id)
    {
        return Regions.FirstOrDefault(st => st.RegionID == id);
    }
}

This seems like a simple thing to do, but I don't know how to get past this error. Any ideas?

1
4
8/22/2011 7:48:30 PM

Accepted Answer

You have two different repositories that each have a separate data context - this is the root problem - your data context should be shared by all your repositories, i.e. you can inject it via constructor injection:

MyDBEntities entities = new MyDBEntities();
_vendorsRepository = new SqlVendorsRepository(entities);
_regionsRepository = new SqlRegionsRepository(entities);
11
8/22/2011 7:53:59 PM

Popular Answer

I came across the same error when I had a Caching layer that was caching look-up Entities and retrieving them from the cache. The cached entities were proxy entities and still had a reference to the DBContext that originally retrieved them.

The main symptom of this is that the first save of a Domain entity with a look up reference worked okay, but subsequent saves failed.

I hope this helps someone, as the problem took 2 days off my life.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow