8

I have an ID with me and I have name with me. So in essence, my method just has these parameters:

public void Foo(int id, string name)
{
}

and I have this piece of logic inside method:

User user = new User(){ Id = id, Name = name };
Db.Entry(user).State = System.Data.EntityState.Modified;
Db.SaveChanges();

That's it. Nothing fancy. I get this error: "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key"

and this answer by Ladislav Mrnka: An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key

suggests to use context.Entry(oldEntity).CurrentValues.SetValues(newEntity); but I don't really have oldEntity with me. Can anybody just please tell me how do I update just 1 property of User? I am getting nuts.

Community
  • 1
  • 1
Jack
  • 6,843
  • 18
  • 53
  • 102
  • why not updateing using the select from entity instead of doing System.Data.EntityState.Modified; – COLD TOLD Aug 06 '12 at 16:46
  • 2
    I don't have code-first experience (and thus won't post an answer), but is `Db` above referring to a database context? If so, contexts in the model-first and database-first worlds are designed to be short-lived objects based on the unit-of-work pattern. Why not create a new context to perform this operation? – Adam Robinson Aug 06 '12 at 16:46
  • @COLD TOLD: Because I want it to be efficient. I don't want to fire 2 requests just for the sake of updating a single property of few tens of properties that I have in my User Model. – Jack Aug 06 '12 at 17:01
  • @AdamRobinson: Thanks. But that doesn't seem to work. – Jack Aug 06 '12 at 17:03
  • Can you post more Code? The posted Code is ok. – LuckyStrike Aug 06 '12 at 17:07
  • @LuckStrike: That is the only piece of code. There is nothing more to post :). Just consider Db as instance of DbContext and that's about it. I don't think posting my User model here is required. – Jack Aug 06 '12 at 17:08
  • @Jack: You don't show where you're creating `Db`. – Adam Robinson Aug 06 '12 at 17:11
  • @Adam: I only create once per request, once created I store it inside HttpContext.Items. Hence even though I make multiple request to DB, it uses same DbContext. Does that help? – Jack Aug 06 '12 at 17:19

1 Answers1

6

I only create once per request, once created I store it inside HttpContext.Items. Hence even though I make multiple request to DB, it uses same DbContext. Does that help?

If any of that "multiple requests to DB" loads user with the same ID you will get this exception. Try to use this:

public void Foo(int id, string name) {
   var user = Db.Users.Local.SingleOrDefault(u => u.Id == id);
   if (user == null) {
      user = new User { Id = id };
      Db.Users.Attach(user);
   } 

   user.Name = name;
   Db.SaveChanges();
}

The code first try to get user instance from already loaded entities (no query to database) and creates a new instance only if the user was not loaded yet.

Ladislav Mrnka
  • 349,807
  • 56
  • 643
  • 654
  • Won't this only update the user if you create and attach that stub entity? If you have an existing user, you're not marking it as modified. – John H Aug 06 '12 at 17:29
  • 1
    @JohnH: It makes changes to attached user so you should not need to change its state - EF should detect the change. – Ladislav Mrnka Aug 06 '12 at 17:30
  • So it does! I always assumed we had to do it for everything unless we specifically attached an entity. Thanks. – John H Aug 06 '12 at 17:37
  • Ladislav Mrnka to the rescue again! – Jack Aug 06 '12 at 17:43
  • @Ladislav: Is that required for delete as well? In short, is it required to that everytime? The "Local"? – Jack Aug 06 '12 at 17:46
  • @Jack: Yes. You can never have two entity instances with the same key attached to the same context instance. – Ladislav Mrnka Aug 06 '12 at 17:46