none
Entity Framework 4.3 Lazy Loading Proxies and changes not being saved on SaveChanges RRS feed

  • Question

  • Hi all,

    got some weirdness (that may be my fault as a result of originally relying on dynamic proxies wiht change tracking...) but I can't seem to "update" any existing entities in my setup.

    if I do "mydbset.Add(entity)" or "mydbset.Remove(entity)" then they do infact get persisted (inserted or deleted) to the DB.

    However, if I do this:

    var myentity = dbcontext.myset.First();
    myentity.property = newvalue;
    //dbcontext.ChangeTracker.DetectChanges();
    dbcontext.SaveChanges();

    it does nothing to that entity at the DB...

    now I suspect that its go something to do with this in my initalization code:

    dbcontext.Configuration.AutoDetectChangesEnabled = false;

    however when I uncomment the commented line above, I can see that if I debug and look at the (ASIDE: please tell me if there is an easier way to fault find EF4s internal structure to watch what's going on in the internal context!!!) "dbcontext.ChangeTracker.Non-public members._internalContext.ObjectContext.ObjectStateManger.Non-Public member..." there are a bunch of "_tobeactioned" type properties, which tells me that there are N-number of items to be added/deleted/modified etc... and it LOOKS to me like there are some that will be affected, but nothing is happening in the DB...

    Now, there *are* children of the entities, which are potentially being changed when the thing is updated also, so perhaps this is causing problems, but I'm really not sure what I'm doing wrong as there doesn't appear to be any errors being raised, its just quietly not doing anything...


    • Edited by noJedi Friday, September 7, 2012 2:17 AM tidy it up
    Friday, September 7, 2012 2:08 AM

Answers

  • Hi SmERloN,

    Welcome to MSDN Forum.

    Based on the issue, you can use TransactionScope to do a batch operation. If there's a step fails, the operation will roll back. For your another question, there's a good solution to persist a changed record. For example, you have a 'Person' record which id is 1, you can use the code below to persist a changed record.

    using (Entities context = new Entities())
                {
                    Person p = new Person();
                    p.Id = 1;
                    p.Name = "ChangedName";
                    context.Entry(p).State = EntityState.Modified;
                    context.SaveChanges();
                }

    The advantage of this method is, it only hit the database once. In original method, you need to query out the record first, and after changing the properties, you need to save it to database, so, it will hit database twice.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us


    • Marked as answer by noJedi Tuesday, September 11, 2012 11:44 AM
    • Edited by Allen_MSDNModerator Wednesday, September 12, 2012 1:22 AM
    Monday, September 10, 2012 2:30 AM
    Moderator

All replies

  • Okay, I think I've resolve the immediate issue.

    was happening in "batch" type setup, and it looks like you can't really call a clear/ re-add type setup without saving in the middle...

    Is there no way to do a batch type of operation where you just delete all the children and then add them back in? and if something fails you aren't in the situation where the "remove" worked but the "add" didn't?

    In and amongst this stuff, I wonder if anyone knows if "dbcontext.Entry(item).State = EntityState.Modified" is better than "DetectChanges()"?

    Presumably the difference is DetectChanges traverses all loaded entities and checks them agains their original state... and Entry() will only affect the state of a specific entry and NOT any children (so if the children were changed you'd need to set thier state to modified also)?

    Can anyone clarify?

    Thanks


    • Edited by noJedi Friday, September 7, 2012 6:04 AM
    Friday, September 7, 2012 6:02 AM
  • Hi SmERloN,

    Welcome to MSDN Forum.

    Based on the issue, you can use TransactionScope to do a batch operation. If there's a step fails, the operation will roll back. For your another question, there's a good solution to persist a changed record. For example, you have a 'Person' record which id is 1, you can use the code below to persist a changed record.

    using (Entities context = new Entities())
                {
                    Person p = new Person();
                    p.Id = 1;
                    p.Name = "ChangedName";
                    context.Entry(p).State = EntityState.Modified;
                    context.SaveChanges();
                }

    The advantage of this method is, it only hit the database once. In original method, you need to query out the record first, and after changing the properties, you need to save it to database, so, it will hit database twice.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us


    • Marked as answer by noJedi Tuesday, September 11, 2012 11:44 AM
    • Edited by Allen_MSDNModerator Wednesday, September 12, 2012 1:22 AM
    Monday, September 10, 2012 2:30 AM
    Moderator
  • Cool thanks Allen,

    However you didn't indicate whether the line setting the state would allow children of the entity to be marked as "modified" or if it would just ensure that the entity would be updated only.

    eg:

    using (Entities context = new Entities())
                {
                    Person p = new Person();
                    p.Id = 3;
                    p.Name = "ChangedName";
    p.FirstChild.Name = "Frank"; // assuming FirstChild is a valid entity... and assuming lazy loading is enabled?! not sure what it would take to make this code "real", but hopefully you get the idea.
                    context.Entry(p).State = EntityState.Modified;
                    context.SaveChanges();
                }

    would FirstChild record get updated?

    Tuesday, September 11, 2012 11:51 AM
  • Hi SmERloN,

    EF manage the entites' state by EntityState, if it marked as 'Modified', when you call SaveChanges method, EF know this entity is to modify. The EntityState is used to tell EF what it should do for the entity.

    I found a mistake in my code and I have edited it. A person in the database which id is 1, if we initiate a Person instance and assign 1 to its id property, after changing its other properties, modify the EntityState to Modified, EF can map the entity with the same key to the exist entity in the database, so when you call SaveChanges, the record is changed.

    Best Regards


    Allen Li [MSFT]
    MSDN Community Support | Feedback to us

    Wednesday, September 12, 2012 1:28 AM
    Moderator