views:

549

answers:

2

I create some items from a class X.

I add them to de base, do SaveChanges and all this...

The class Y has a relationship many-to-many with X.

Using another Context, I create a Y instance, putting into the collection of X the elements I've created.

I add Y to Y entity set, it is fine.

When I do Context.SaveChanges(), I get:

A value shared across entities or associations is generated in more than one location. Check that mapping does not split an EntityKey to multiple server-generated columns.

Have you ever seen this error?

EDIT: at the beginning, I've put 1-to-many, after I've noticed it is in fact many-to-many.

EDIT 2: showing the way this is being done. Unlike many people while using .net, we do use layers (business, data...). This is the test case:

[TestMethod]
public void WorksWithAreaCategories()
{
    using (new TransactionScope())
    {
     //arrange
     var context = ContextFactory.Create();
     var categoryBusiness = new CategoryBusiness(context);
     var category = new Category
       {
        Name = "TestCategory###"
       };
     categoryBusiness.Add(category);

     var areaBusiness = new AreaBusiness(context);
     var area = new Area
       {
        Name = "TestArea###",
        Description = "TestAreaDescription###",
        Categories = new List<Category> {category}
       };

     //act
     areaBusiness.Add(area);

     //assert
     var areaFromDb = areaBusiness.FindById(area.AreaID);
     Assert.IsNotNull(areaFromDb.Categories);
     Assert.IsTrue(areaFromDb.Categories.Count > 0);
     Assert.IsTrue(areaFromDb.Categories.Any(c => c.CategoryID == category.CategoryID));
    }
}

They share the same context. The business layers call SaveChanges in the end of each Add.

A: 

When the error says "more than one location", it really means more than one context. Data "belongs" in a specific context and you get problems if you try to move it between contexts.

There are 2 ways to fix it:

  • Do everything in the same context
  • When you create the Y instance, read the X elements from disk, so that they are in the same context, before adding the X elements to Y.

EDIT based on comment:

Try using a single save changes.

Shiraz Bhaiji
Even using the same context, I get the same problem. =/
Victor Rodrigues
hmm, I can't because they're different operations. I use these operations through a business layer so I can't save only at the last one, I'll update the question to show to you the way it is being done. What is interesting is that the same thing doesn't throw any error in other many-to-many relationships.
Victor Rodrigues
I didn't understand the second option, maybe I can solve through this way. When I create the Y instance, I do a linq query to load the X elements from context, I don't use the entity objects directly, because I don't have them (the test case works with POCOs, not the entities, I have to map them)
Victor Rodrigues
Even not Saving the context while inserting the category (X), I get the same problem :S
Victor Rodrigues
Scary comment: event not ADDING the Xs previously, I get the same problem.
Victor Rodrigues
A: 

How I resolved it:

After adding both of them, I established the relationship with Update.

[TestMethod]
public void WorksWithAreaCategories()
{
    using (new TransactionScope())
    {
     //arrange
     var context = ContextFactory.Create();
     var categoryBusiness = new CategoryBusiness(context);
     var category = new Category
         {
          Name = "TestCategory###"
         };
     categoryBusiness.Add(category);

     var areaBusiness = new AreaBusiness(context);
     var area = new Area
         {
          Name = "TestArea###",
          Description = "TestAreaDescription###",
         };
     areaBusiness.Add(area);

     //act
     area.Categories = new List<Category> { category };
     areaBusiness.Update(area);

     //assert
     var areaFromDb = areaBusiness.FindById(area.AreaID);
     Assert.IsNotNull(areaFromDb.Categories);
     Assert.IsTrue(areaFromDb.Categories.Count > 0);
     Assert.IsTrue(areaFromDb.Categories.Any(c => c.CategoryID == category.CategoryID));
    }
}
Victor Rodrigues
Could you post the code that worked?
Shiraz Bhaiji
it's here now ;)
Victor Rodrigues