none
How does the ObjectContext.Refresh method work when specifying RefreshMode.StoreWins? RRS feed

  • Question

  • Hi,

    I want to ask how the "Refresh" method of the "ObjectContext" class works, assuming we have an entity set called "Customers", what will happen when I call the following code: 

    MyObjectContext.Refresh(RefreshMode.StoreWins, MyObjectContext.Customers);

    I used to use the previous code to refresh the entity set before calling any query referring to it like:

    var customer1 = MyObjectContext.Customers.Where( cust => cust.ID == 5);

    I really don't understand what is going on in the background, is it a query to get all rows of the underlying table to rebuild the entity set again? or what?

    Cheers





    • Edited by Imad Ozone Tuesday, April 24, 2012 11:52 AM
    Wednesday, March 28, 2012 5:14 AM

Answers

  • Hi Imad Ozone,

    Ok, I think the demo below can help you to understand it.

    using (TestContainer context = new TestContainer())
                {
                    TestTable test = (from t in context.TestTables where t.ID == 1 select t).Single();
                    test.Name = "clientModify";
                    try
                    {
                        context.SaveChanges();
                    }
    
                    catch (Exception e)
                    {
                        //the test.Name will be "clientModify"
                        context.Refresh(RefreshMode.ClientWins, test);
    
                        //the test.Name will be "databaseModify"
                        context.Refresh(RefreshMode.StoreWins, test);
                        context.SaveChanges();
                    }
                }

    The test.Name is "Original". Adding a break point at "context.SaveChanges" method in the try block, then run the application, after the debug stopping, modify the Name to "databaseModify" in the database, press F5 to start debugging, the exception will be catched.

    Best Regards


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

    • Marked as answer by Imad Ozone Monday, April 2, 2012 8:00 AM
    Monday, April 2, 2012 6:42 AM
    Moderator

All replies

  • Hi,

    Is my question very difficult to answer or what, guys? Would you please provide me with anything to start looking at?

    Cheers


    • Edited by Imad Ozone Thursday, March 29, 2012 6:08 AM
    Thursday, March 29, 2012 4:47 AM
  • Hi Imad Ozone,

    Welcome to MSDN Forum.

    The correct way to use ObjectContext.Refresh method is putting it in the “catch” section to handle concurrency.

    RefreshMode.StoreWins doesn’t mean to hit database and query out the data again, it will refresh the data with datasource, which you have already queried out.

    Below is a demo that demonstrates the common usage of ObjectContext.Refresh method, please refer to it.

    try
    {
        // Try to save changes, which may cause a conflict.
        int num = context.SaveChanges();
        Console.WriteLine("No conflicts. " +
            num.ToString() + " updates saved.");
    }
    catch (OptimisticConcurrencyException)
    {
        // Resolve the concurrency conflict by refreshing the 
        // object context before re-saving changes. 
        context.Refresh(RefreshMode.ClientWins, orders);
    
        // Save changes.
        context.SaveChanges();
        Console.WriteLine("OptimisticConcurrencyException "
        + "handled and changes saved");
    }
    

    You can also refer to the articles below, I think they can help you.
    Saving Changes and Managing Concurrency

    On Entity Framework, Concurrency

    Best Regards


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

    Thursday, March 29, 2012 6:39 AM
    Moderator
  • Thank you Allen for you replay, I really saw a lot of examples for ObjectContext.Refresh and all of them were about handling the concurrency by passing RefreshMode.ClientWins to that method I was seeking for the best way to refresh the entity set when the db table data is changed, for better understanding let us assume we have:

    Database Table : tblCustomer

    ObjectContext : MyObjectContext

    Entity set : CustomerEntitySet .. referring to that table  

    and I called the linq statement though a button click:

    var cust = MyObjectContext.CustomerEntitySet.ToList();

    after that I changed the data outside my app though a SQL query for example:

    Update tblCustomer Set LastName = '' 


    Now I want to get the entity set again but with the changes I made though the sql query. What should I do?

    Is the following code a solution?

    MyObjectContext.Refresh(RefreshMode.StoreWins, MyObjectContext.CustomerEntitySet);

    or there is another way for that?

    Cheers



    • Edited by Imad Ozone Thursday, March 29, 2012 8:26 AM
    Thursday, March 29, 2012 8:24 AM
  • Hi Imad Ozone,

    RefreshMode.StoreWins will rewrite the modified property's value to the data source value, and change the entity's state to "Unchanged". For example, the "LastName" property you queried out from the database is "DatabaseName", then you modify the value to "ModifyName" in the database, if the concurrency occurs, the RefreshMode.StoreWins will rewrite the value to "DatabaseName" and change the entity's state to "Unchanged". If you want the latest value "ModifyName", you need to use RefreshMode.ClientWins. But, the state of the entity will be "Modified" before calling SaveChanges method.

    Based on the scenario you post, the solution can work.

    Best Regards


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

    Friday, March 30, 2012 7:24 AM
    Moderator
  • RefreshMode.StoreWins will rewrite the modified property's value to the data source value, and change the entity's state to "Unchanged". For example, the "LastName" property you queried out from the database is "DatabaseName",

    That is what I was talking about I mean performing a query against the database table to get the value and set the entity to its original value "UnChanged" through calling :

    MyObjectContext.Refresh(RefreshMode.StoreWins, MyObjectContext.Customers)  

    but you said before that :

    RefreshMode.StoreWins doesn’t mean to hit database and query out the data again, it will refresh the data with datasource, which you have already queried out.

    How come?!!

    Which opinion is the right one?! I'm really lost here!

    Cheers


    • Edited by Imad Ozone Sunday, April 1, 2012 11:54 AM
    Sunday, April 1, 2012 11:53 AM
  • Hi Imad Ozone,

    Ok, I think the demo below can help you to understand it.

    using (TestContainer context = new TestContainer())
                {
                    TestTable test = (from t in context.TestTables where t.ID == 1 select t).Single();
                    test.Name = "clientModify";
                    try
                    {
                        context.SaveChanges();
                    }
    
                    catch (Exception e)
                    {
                        //the test.Name will be "clientModify"
                        context.Refresh(RefreshMode.ClientWins, test);
    
                        //the test.Name will be "databaseModify"
                        context.Refresh(RefreshMode.StoreWins, test);
                        context.SaveChanges();
                    }
                }

    The test.Name is "Original". Adding a break point at "context.SaveChanges" method in the try block, then run the application, after the debug stopping, modify the Name to "databaseModify" in the database, press F5 to start debugging, the exception will be catched.

    Best Regards


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

    • Marked as answer by Imad Ozone Monday, April 2, 2012 8:00 AM
    Monday, April 2, 2012 6:42 AM
    Moderator
  • This is very good now :)

    Thank you Allen. 

    Monday, April 2, 2012 8:01 AM