locked
EF4 Concurrency Mode=Fixed causes related Entities to be saved RRS feed

  • Question

  • Greetings, I have been keeping an eye on EF4 performance using SQL Query Profiler.  I noticed that when I expect to save one object to the database, it is actually saving that object plus all related objects.

    My Entities are named User, Session, and Workstation.  The User and the Workstation tables each have 2 columns (the primary key and a Timestamp column) with Concurrency Mode=Fixed, since these Entities can be edited in a form.  The Session object does not have any Concurrency Mode set on any columns.  The Session object contains 2 foreign keys, one each to User and Workstation.  At the time the user starts the software, I create the Session entity and relate it to the User and the Workstation where they logged in.  I set the OnlineTime in the Session to DateTime.Now.

    EDIT: I'm using Foreign Key Associations based on the Foreign Keys that I created in the database (as opposed to Independent Associations).  The Foreign Keys go FROM the Session TO the User and TO the Workstation via columns in the Session table named UserId and WorkstationId.

    When I call SaveChanges on the Context, all 3 Entities are saved, even though I never changed the User or Workstation objects.  I just created a Session object that was linked to a User and a Workstation.  This causes the Timestamp column to increment on both the linked User and Workstation records, which is not what I want at all.

    Furthermore, when the user closes the app, I just change their OfflineTime in the Session object to be DateTime.now and again call context.SaveChanges().  Again, all 3 objects are updated in the database.  This 2nd time is even more egregious because I have only touched a single property in the Session object, not modifying relationships at all, and it still increments the Concurrency Mode=Fixed timestamp columns in the linked User and Workstation objects, and reads back the new values during the SaveChanges operation.

    How can I change this behavior so that only entities that are actually modified, are saved to the database.  Creating a relationship between the Session and User/Workstation Entities should not cause the User/Workstation Entities to be re-saved to the database because all the Foreign Keys reside within the Session object.

    Thanks in advance for your help.  I will be happy to provide a simple sample solution that demonstrates this issue.

    My environment is Visual Studio 2010 Pro Trial and MS SQL Server 2005.

    • Edited by HugeHugh Friday, June 18, 2010 8:20 PM Mention that I'm using FK associations
    Friday, June 18, 2010 4:54 PM

Answers

  • Thank you very much for your following up!   I am waiting the feedback from the product team.  

    Besides, based on my test, only setting the foreign key column directly works fine at my side.  Please note, the corresponding User and Workstation entities are not loaded to the client side. 

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by HugeHugh Thursday, June 24, 2010 4:17 PM
    Wednesday, June 23, 2010 5:15 AM
  • Lingzhi Sun, you're a life saver! :)

    In my app I have an Entity Context that stays alive for the entire life of the application.  It needs to do that to take advantage of the built-in caching so as not to keep re-fetching certain Entities from the database.

    So the solution is to not use that Context, but to use a new and different Context just for the Save operation, when I don't want to affect related Entities.

    I set up the Foreign Keys in the new session object like this:

    OpenSession = new zSession()
    {
    	OnlineTime = DateTime.Now,
    	zUserId = DefaultUser.zUserId,
    	zWorkstationId = DefaultWorkstation.zWorkstationId
    };

    And my code to save the new Session object, looks like this:

    using (Entities saveContext = new Entities())
    {
        saveContext.zSessions.AddObject(OpenSession);
        saveContext.SaveChanges();
    }

    And my code to save the modified Session object, looks like this:

    using (Entities saveContext = new Entities())
    {
    	saveContext.zSessions.Attach(OpenSession);
    	saveContext.ObjectStateManager.ChangeObjectState(OpenSession, System.Data.EntityState.Modified);
    	saveContext.SaveChanges();
    }

    In both cases, only the affected Session object is saved, not the related User and Workstation objects.  So this is now resolved!  :)

    Thank you very much for your valuable assistance.

    Kind Regards,

    Hugh

    • Marked as answer by HugeHugh Thursday, June 24, 2010 4:17 PM
    Thursday, June 24, 2010 4:14 PM

All replies

  • Hello,

     

    Welcome to EF forum & thank you for your posting!

     

    I can repro the issue based on your description.   The issue occurs if the related User and Workstation entities have been loaded into the context.   If we directly set the foreign key columns of the Session entity, the related User and Workstation entities are not updated.

    =======================================================================

    Session session = new Session() { SessionID = 1, Time = DateTime.Now };

    session.UserID = 1;

    session.WorkstationID = 1;

    context.Sessions.AddObject(session);

    context.SaveChanges();

    =======================================================================

     

    However, if the two related entities are loaded, even we still use the foreign key columns to set the relationships, the User and Workstation are updated.  

     

    Could you please tell me the impact on your application?   I will consult the product team to see if it is a by design feature or product issue.  

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, June 22, 2010 2:31 AM
  • Good morning Lingzhi Sun, and thank you for your reply.

    Before I posted my problem here on MSDN forums, I tried many variations.

    I tried just setting the Foreign Key ID's of the related Entities, as you suggested.

    I also tried setting the Navigation properties directly, like this:

    =======================================================================
    Session session = new Session() { SessionID = 1, Time = DateTime.Now };
    session.User = CurrentUser;
    session.Workstation = CurrentWorkstation;
    context.Sessions.AddObject(session);
    context.SaveChanges();
    =======================================================================

    I even tried using Detach() and Attach() to remove the session from the Context, set up the Foreign Keys, and put it back in the Context.

    None of these things worked.  All of these variations always result in 3 objects being saved, instead of 1, when I call context.SaveChanges().

    I can easily make it go back to just saving the 1 Session object, by removing the Concurrency Mode=Fixed on the properties in the User and Workstation Entities.  However, I was hoping to use the EF4 built-in features for handling Optimistic Concurrency Exceptions by using these settings.

    Thank you for your help.  I will be very interested to see what the Product team has to say about this issue.

    Kind Regards,
    Hugh
    Tuesday, June 22, 2010 3:26 PM
  • Thank you very much for your following up!   I am waiting the feedback from the product team.  

    Besides, based on my test, only setting the foreign key column directly works fine at my side.  Please note, the corresponding User and Workstation entities are not loaded to the client side. 

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    • Marked as answer by HugeHugh Thursday, June 24, 2010 4:17 PM
    Wednesday, June 23, 2010 5:15 AM
  • Hi Hugh,

     

    The product team is investigating this issue.  I will get you informed as soon as I receive any feedbacks. 

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, June 24, 2010 3:01 AM
  • Lingzhi Sun, you're a life saver! :)

    In my app I have an Entity Context that stays alive for the entire life of the application.  It needs to do that to take advantage of the built-in caching so as not to keep re-fetching certain Entities from the database.

    So the solution is to not use that Context, but to use a new and different Context just for the Save operation, when I don't want to affect related Entities.

    I set up the Foreign Keys in the new session object like this:

    OpenSession = new zSession()
    {
    	OnlineTime = DateTime.Now,
    	zUserId = DefaultUser.zUserId,
    	zWorkstationId = DefaultWorkstation.zWorkstationId
    };

    And my code to save the new Session object, looks like this:

    using (Entities saveContext = new Entities())
    {
        saveContext.zSessions.AddObject(OpenSession);
        saveContext.SaveChanges();
    }

    And my code to save the modified Session object, looks like this:

    using (Entities saveContext = new Entities())
    {
    	saveContext.zSessions.Attach(OpenSession);
    	saveContext.ObjectStateManager.ChangeObjectState(OpenSession, System.Data.EntityState.Modified);
    	saveContext.SaveChanges();
    }

    In both cases, only the affected Session object is saved, not the related User and Workstation objects.  So this is now resolved!  :)

    Thank you very much for your valuable assistance.

    Kind Regards,

    Hugh

    • Marked as answer by HugeHugh Thursday, June 24, 2010 4:17 PM
    Thursday, June 24, 2010 4:14 PM
  • Hi Hugh,

     

    It's my pleasure and I am very happy to hear we have some workaround on this isssue.  

    Some updated information:  the product team has confirmed that it is a product issue of EF4.   The workaround is what we used by only setting the foreign key column values. 

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Monday, June 28, 2010 9:11 AM
  • Lingzhi Sun, I'm still having a problem, maybe you can help.

    How can I apply the technique you suggested, when the Entity to be saved participates in a Many-to-Many relationship?

    I'm becoming a bit discouraged, because I can't find a reliable pattern to apply when I want to save my objects.  It seems each object or each relationship presents a new challenge that I must figure out as I go.  It is taking me a long time to come up to speed with Entity Framework.

    I really appreciate your help.  I just need to know what to do when I want to save an object that participates in a Many-to-Many relationship.

    I tried to use the technique you suggested, of creating a separate context.  Here are the problems I ran into:

    1) If I try to add an object to the 2nd context, that already exists in the main context, I get an exception that the object can't be tracked by multiple ObjectStateTracker's.

    2) If I try to Detach the object from the 1st context, it doesn't detach the related objects.  The asymmetry between subobject behavior when using Detach() and Attach() is a big source of frustration for me.  As you know, Detach() only detaches the one object, but Attach() attaches that object and all related ones.

    3) There are no Foreign Key properties to set on the Many to Many relationship because the Linking table has "disappeared" - a feature of Entity Framework when using a linking table that only has 2 keys.

    Please help, I'm having a hard time.

    Hugh

    Monday, June 28, 2010 3:32 PM
  • Hi Hugh,

     

    Do you mean the two entities with many-to-many relationships also contain the timestamp columns which leads to the original issue of this thread?   If so, I cannot figure out any good workarounds now, and I will consult the product team again.   But it seems to be hard to fix this one because of some product issue which we have discussed. 

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, June 29, 2010 9:58 AM
  • Hi Lingzhi Sun,

    Please inform me how I can keep up-to-date on this product issue.

    What is the bug number that I can use to track it?

    What is the anticipated time frame to address this issue?

    When is another Entity Framework release forthcoming?

    Thanks,

    Hugh

    Tuesday, June 29, 2010 6:22 PM
  • Hi Hugh,

     

    I am communicating with the product team.   If I receive any updated information, I will get back to you ASAP.

     

    Good day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, July 1, 2010 5:47 AM
  • Our ability to wait has expired.  We expected that MS Entity Framework was a production-ready ORM.  This was a big mistake.

    We have switched to nHibernate and we will never switch back to MS Entity Framework.  You've lost us permanently.  I will also communicate the myriad problems we experienced to all of my professional colleagues.

    Microsoft Entity Framework should be labeled a BETA!  You have alienated your users with such a poor product.  At least if it was labeled a BETA then people could make the decision to use it knowing to expect problems.

    Tuesday, July 6, 2010 4:12 PM
  • We face a similar problem with a business app & concurrent access .. Any news on that issue?

    Thanks, Linard

    • Proposed as answer by robbo86 Saturday, September 4, 2010 5:53 AM
    Saturday, July 24, 2010 11:21 AM
  • As annoying as it is that Microsoft does this, I have found that atleast with these issues (with my using self tracking entities) I have been able to adjust their template to work around this problem. The key is to adjust the AcceptChanges method to detatch the entity from the objectContext if it's entityState is unchanged. Therefore EF only has knowledge about the entities i WANT it to update. Its a bit annoying having to babysit EF like that, but it does seem to work. 

    I have had to do some major reworking to the EF self-tracking entity template to get it to work nicely over WCF calls (such as only sending over the wire properties that have actually changed, etc) and this is one little doosey that looks to be typical of MS pushing out code before it has properly been tested. 

    Let me know if this helps at all or you would like some code as an example. I'm afraid my version of this method is a fair bit different to the template one so it might not be that helpful, but the general idea is there. Just detach objects that dont need to be updated.

     

    Saturday, September 4, 2010 6:00 AM
  • robbo86,

    I could to use your sample if you share it. I'm developing an ASP.NET application which ran into same problem reported by HugeHugh and I'm considering options to fix EF4 behavior or to change my ORM, as he did.

    Microsoft,

    any updates on this subject?

    TIA,

    Rubens

    Tuesday, September 7, 2010 2:03 AM
  • Greetings,

    My final solution was to use Entity Framework 1.0 in .Net Framework 3.5 which doesn't suffer from this problem.

    I tried NHibernate but it forced me into an architecture that didn't seem correct for our application.  EF 1.0 has been easy to use, after I stopped using the default code generation and went to a template-based approach which I have also customized extensively for use with WCF:

    http://blogs.msdn.com/b/dsimmons/archive/2008/10/27/using-t4-templates-to-generate-ef-classes.aspx

    Kind Regards,

    Hugh

    Thursday, September 23, 2010 4:23 PM
  • Greetings Lingzhi Sun,

    My brother recently attended a seminar about Entity Framework, and he was told that there is a new version of Entity Framework 4 that is supposed to be released in early 2011.

    Can you confirm that there is a new Entity Framework release that is coming?  If so, when is the exact date?

    Finally, can you confirm whether the original problem I posted in this thread on June 18 has been addressed in that new EF release?  If so, that would be really great news, and I would be able to switch to .Net framework 4.0 and Visual Studio 2010.

    Please reply to let me know about the new EF release and if it might have this Concurrency issue fixed in it.

    Thanks,

    Hugh

    Monday, December 13, 2010 10:22 PM
  • Hi Hugh,

    Glad to hear from you!   Could you please open a new thread to discuss this issue and tell me the thread link?  I will follow up on the new thread and try to get connected with the product team to check the status of the issue. 

    For the new release of EF4, I think it is an updated version which is release with the VS2010 SP1.  

    Good day!

     


    Michael Sun [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, December 14, 2010 1:23 AM
  • I don't want to open a new thread because it is important to retain the CONTEXT of this thread!  We have been discussing an important issue and I do not want to have to re-explain the issue in a new thread.

    I have a relevant question that pertains to the original post.  Please reply to my question.  Specifically, I want to know if the original problem I posted about on June 18 2010 is addressed by any forthcoming EF4 release.  Here's the URL of the thread:

    http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/e6a8bd4b-b4ad-4459-904b-db21f2e0e5ab

    Thank you for your prompt reply!

    Hugh

    Friday, December 17, 2010 10:17 PM
  • Although I have no idea why you require a new thread to inquire about progress, that appears to be the only way to get a response out of you.

    Here's your new thread:

    http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/b2d01f56-d7a2-4322-9936-1018e0bfa811

    Please reply to let me know progress of this important issue!

    Hugh

    Monday, December 27, 2010 5:22 PM
  • Hey folks over there,

    we are ancountering exactly the same problem as HugeHugh and it's a very crucial issue for us as we are in the process of developing a fully fledged LOB application based on EF 4. We definitely need concurrency handling in that application andI I think noone would ever seriously put this in question. Our testers started seeing concurrency exceptions (which we wrap into meaningful error messages) all over the place since the introduction of EF 4.

    I can only support HugeHugh in his opinion that the least that we as users of official Microsoft technology can expect is

    a) an info whether this issue has been recognized by MS as a bug or not and

    b) if so (which I expect, otherwise I would expect to receive instructions on what we did wrong) when and how this elementary issue will get fixed

    Just to be clear: I do not mean to ____ around here without any reason. All I am asking for is that MS recognizes that they put us in a very bad positions. Managers simply don't have much of an understanding if software engineers come to them with things like this asking for a budget to completely redevelop an applications data access logic.

    In case this is not the appropriate platform to bring the issue up to somebody at MS I would really appreciate if someone could route the message to the responsible contact at MS.

    Hope to hear from you VERY soon

    Thomas.

    Thursday, January 6, 2011 6:26 PM
  • Hi,

    The issue mentioned in this thread is a bug, and has been addressed in a hotfix recently. You can get more details about the hotfix here: http://support.microsoft.com/kb/2390624

    Please let us know how this works out for you - currently, you have to contact Microsoft Customer Support in order to get the hotfix.

    Faisal Mohamood | Program Manager | Entity Framework Team

    Monday, January 17, 2011 4:56 AM
  • Running into the same issue..

     

    Could someone please post a diff of the hotfix's T4 template VS the original one?

     

     

    Thanks.
    Koen

    Sunday, January 23, 2011 8:06 PM
  • Is there any chance that this hotfix will be rolled into the upcoming .NET 4.0 update?  Do we know when this fix will land as a non-hotfix or publically available hotfix?

     

    Friday, March 4, 2011 6:48 PM
  • The above link doesn't have any file do download.

     

    I have the same issue.

    Tuesday, July 19, 2011 9:54 AM