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

Every Region is included in a checkbox list on my page for becoming a vendor. I want to update the VendorRegions database with the VendorID and RegionID for each area that has been checked.

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

My controller code is as follows:

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
    }
}

My vendor repository code is as follows:

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

When I attempt to save my vendor, the error appears at_entities.Vendors.Context.AddObject("Vendors", vendor); . Here is my Regions repository code in case you need it as well:

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

I don't know how to get past this mistake, even though it seems like a straightforward thing to accomplish. Any thoughts?

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

Accepted Answer

Your data context should be shared by all of your repositories, i.e. you may inject it through constructor injection. You have two separate repositories, each of which has a separate data context.

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

Popular Answer

When I used a caching layer to cache look-up entities and get them from the cache, I saw the identical issue. The DBContext that first fetched the cached entities, which were proxy entities, was still referenced in them.

The key sign of this is that subsequent save attempts for a Domain object with a look up reference failed after the initial successful save.

Since the issue cost me two days of my life, I hope this will help someone.



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