views:

299

answers:

3

Hello,

I'm using .NET 3.5 SP1 in ASP.NET MVC application.

While using ObjectContext with Http Request lifetime, and trying to attach an entity ALREADY present in context, we get error: "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key." For Example, the code :

Category newCategory = new Category {CategoryId = CategoryIdSelected};
ctx.AttachTo("CategorySet", newCategory);

will give error if 'Category' with CategoryId = CategoryIdSelected exists in ObjectContext.

Modified code to check for existing entity:

Category newCategory = new Category {CategoryId = CategoryIdSelected};
ObjectStateEntry stateEntry = null;

if( ctx.ObjectStateManager.TryGetObjectStateEntry(newCategory, out stateEntry)){
   //EntityObject already attached in context, get it
    newCategory = (EntityObject)stateEntry.Entity;
}else{
    ctx.AttachTo("CategorySet", newCategory);   
}

The modified code is still giving same error: "[System.InvalidOperationException] = {"An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."

Please advise ?

Thank You

+1  A: 

Your code is using two different contexts. You check one, and then attach to the other:

if( csContext. //...){
   ///
}else{
    ctx. // ...
}

The entity appears to be in ctx, but not in csContext. My advice is to use only one context at a time whenever possible; it's much less confusing.

Update

OK, you've changed the code in your question.

My guess is that your stub object doesn't have an EntityKey, so TryGetObjectStateEntry is returning false. Try:

if( ctx.ObjectStateManager.TryGetObjectStateEntry(
    new EntityKey("MyEntities.CategorySet", "CategoryId", CategoryIdSelected), 
    out stateEntry)){

Obviously, replace "MyEntities" with the actual model name.

Craig Stuntz
Thanks! It is the same context. I have corrected the typo.
dev
A: 

Thanks. It works with EntityKey.

MSDN says for BOTH methods:

ctx.ObjectStateManager.TryGetObjectStateEntry(Object, out stateEntry))

and

ctx.ObjectStateManager.TryGetObjectStateEntry(EntityKey, out stateEntry))

will have: "A Boolean return value that is true if there is a corresponding ObjectStateEntry for the given EntityKey; otherwise, false." implying EntityKey is required for Entity STUB.

dev
A: 

QUESTION ADDENDUM:

More problems attaching Entities when using ObjectContext having lifetime of Http Request.

For Example, if we have 'AppUser','Category' and Department entities.

public class AppUser : System.Data.Objects.DataClasses.EntityObject{   
 public int Uid {get; set;}   
 public string UserName {get; set;}   
 public string Password {get; set;}   
 public Department Dept {get; set;}   
 public Category catg {get; set;}
 ...........   
}

AppUser has relationship with Department and Category Entities. Now when trying to attach 'user':

user = new AppUser{Uid=1,catg = new Category {categoryId=10}, Dept = new Department{departmentId=101}, ...}
var key = ctx.CreateEntityKey("AppUserSet", user);
if (ctx.ObjectStateManager.TryGetObjectStateEntry(key, out stateEntry)) {

will work ONLY if, in context :

  • there is NO Category with categoryId=10, and
  • there is NO Department with departmentId=101

One option, is to ensure context does not have attached entities by always retrieving using NOMERGE NoTracking option. BUT I found following problems with MergeOption.NoTracking:

  • Second call would still result in db hit
  • You don't get EntityKeys on EntityRefs. So EntityKey of XXXReference is null,which means NO FK Stub. Please see.
    How to get EntityKey of Reference w/o loading both ends (both entities)?
  • Even though Entity are Detached, they have a reference to the DataContext (via entity._realtionships._context). Please see.

Please advise.

Thank You.

dev