locked
DbSet update issue RRS feed

  • Question

  • The following code does not update the database:

    using (FooEntities context = new FooEntities ())
    {
       foreach (tblFoo r in context.tblFoos)
       {
          r.fieldFoo = "foo";
       }
       ontext.SaveChanges();
    }

    However, the following works:

    using (FooEntities context = new FooEntities ())
    {
       foreach (tblFoo r in context.tblFoos)
       {
          r.fieldFoo = "foo";
          context.Entry(r).State = EntityState.Modified;
       }
       context.SaveChanges();
    }

    When the record r is retrieved via a Linq statement, its updating does not seem to require context.Entry(r).State = EntityState.Modified;

    Could anyone shed some light on this?


    Hong

    Tuesday, December 16, 2014 6:04 PM

Answers

  •  

    I feel at this point of time the only way to find out whether entities are tracked or not is actually testing it.  I do not see any general rules that can be followed to determine whether entities are automatically tracked.  In the case of entities not tracked in my first post, the entities are obtained from the context (foreach (tblFoo r in context.tblFoos)) too. My guess is that in this case, a copy of the DbSet is created and it is detached from the context.

    That first example you can do it in EF 5 and below. But with EF 6, you have to actally to some kind of a get/read of the object and bring it into context before you can update or delete the object.

    http://blogs.msdn.com/b/alexj/archive/2009/03/27/tip-9-deleting-an-object-without-retrieving-it.aspx

    If using ObjectContext and doing the samething to update the object in the example instead of deleteing the object by attaching the object to the ObjectContext,  updating the object and then saving it, EF knew the object had changed. You do the samething in the example using DBcontext in either case delete or update of the object, and EF 6 flatout will ignore it.

    It's now you have to actally get the object (read it) for an update or delete of the object, becuase otherwise, EF 6 is not going to invoke the action to do anything with the object. In you first example and from my standpoint, you actally never got an individual object to get it into context. You just rolled over the objects in a loop, which didn't work for you. You had to force the state to "Modified".

    One is forced to use DBConext in EF 6. You can use ObjectContext in some situation like using it to do queries with Entity-SQL. But other than that and trying to use Objectcontext in EF 6, one quickly finds out that one has got hell to pay in order to use it and abandons it quickly.

    It is what it is.

    • Marked as answer by Hong (MA, USA) Wednesday, December 17, 2014 3:10 PM
    Wednesday, December 17, 2014 2:52 PM

All replies

  • The first example EF doesn't consider the object to have changed so the state of the object is not Modified. You should get the object's state and check it. I think you'll find that the object is not modified, even through you changed the value of the object's property.

    http://msdn.microsoft.com/en-us/data/jj592676.aspx

    Tuesday, December 16, 2014 8:57 PM
  • Thanks for the clarification.

    Is there a good online article on when an entity is tracked and when not?  The issue with the first scenario is the entity is not tracked unless there is this statement: context.Entry(r).State = EntityState.Modified;


    Hong

    Tuesday, December 16, 2014 9:12 PM
  • http://www.c-sharpcorner.com/UploadFile/ff2f08/working-with-change-tracking-proxy-in-entity-framework-6-0/

    I think you'll want to investigate how "change tracking" works in EF. You may also want to look at "change notification" in EF entities Bing and Google are your friends.

    Tuesday, December 16, 2014 10:13 PM
  • As usual, I did extensive search before posting the question.  I am wondering if I was using wrong key word combinations because I could not find a clear explanation about when entities are tracked and when not.

    For example, the an entity is obtained and modified in the following way:

    tblFoo r = context.tblFoos.First(r => r.Name == sName);

    r.fieldFoo = "Foo";

    context.Entry(r).State = EntityState.Modified is NOT needed before calling context.SaveChanges().


    Hong

    Wednesday, December 17, 2014 12:29 AM
  • In your last exsmple, you actually got an object for update in the context and then updated the object. A change notification must have fired to mark the object as dirty/modified.
    Wednesday, December 17, 2014 1:57 AM
  • I feel at this point of time the only way to find out whether entities are tracked or not is actually testing it.  I do not see any general rules that can be followed to determine whether entities are automatically tracked.  In the case of entities not tracked in my first post, the entities are obtained from the context (foreach (tblFoo r in context.tblFoos)) too. My guess is that in this case, a copy of the DbSet is created and it is detached from the context.

    Hong

    Wednesday, December 17, 2014 12:10 PM
  •  

    I feel at this point of time the only way to find out whether entities are tracked or not is actually testing it.  I do not see any general rules that can be followed to determine whether entities are automatically tracked.  In the case of entities not tracked in my first post, the entities are obtained from the context (foreach (tblFoo r in context.tblFoos)) too. My guess is that in this case, a copy of the DbSet is created and it is detached from the context.

    That first example you can do it in EF 5 and below. But with EF 6, you have to actally to some kind of a get/read of the object and bring it into context before you can update or delete the object.

    http://blogs.msdn.com/b/alexj/archive/2009/03/27/tip-9-deleting-an-object-without-retrieving-it.aspx

    If using ObjectContext and doing the samething to update the object in the example instead of deleteing the object by attaching the object to the ObjectContext,  updating the object and then saving it, EF knew the object had changed. You do the samething in the example using DBcontext in either case delete or update of the object, and EF 6 flatout will ignore it.

    It's now you have to actally get the object (read it) for an update or delete of the object, becuase otherwise, EF 6 is not going to invoke the action to do anything with the object. In you first example and from my standpoint, you actally never got an individual object to get it into context. You just rolled over the objects in a loop, which didn't work for you. You had to force the state to "Modified".

    One is forced to use DBConext in EF 6. You can use ObjectContext in some situation like using it to do queries with Entity-SQL. But other than that and trying to use Objectcontext in EF 6, one quickly finds out that one has got hell to pay in order to use it and abandons it quickly.

    It is what it is.

    • Marked as answer by Hong (MA, USA) Wednesday, December 17, 2014 3:10 PM
    Wednesday, December 17, 2014 2:52 PM
  • Thanks a lot for the elucidation.  The 4-year old web project is using EF5.  I may update it to EF6 next year.

    I will just test EF related code carefully assuming nothing.  


    Hong

    Wednesday, December 17, 2014 3:10 PM