none
EF 4.1 DbContext.Entry.Property.IsModified BUG RRS feed

  • Question

  • Hello,

    I am following the Microsoft Tutorial "Using DbContext in EF 4.1 Part 5: Working with Property Values" located at http://blogs.msdn.com/b/adonet/archive/2011/01/30/using-dbcontext-in-ef-feature-ctp5-part-5-working-with-property-values.aspx

    The DbContext.Entry.Property.OriginalValue and DbContext.Entry.Property.CurrentValue both have getters and setters.  I am not sure why OriginalValue should ever be editable.  Since both can be changed, IsModified returns true even if the CurrentValue and the OriginalValue match. I made an error in my initial post here.  What I intended to say was, if I change the CurrentValue and then change it back to the OriginalValue, it seems to me that IsModified should return false. It does not. 

    Here is a test using the data provided by the tutorial listed above:

     

                   
    
    using (var context = new UnicornsContext())
    {               string newName = "Chica";
    
                   var unicorn = context.Unicorns.Find(1);
                   string originalName = context.Entry(unicorn).Property(u => u.Name).OriginalValue;
                   string currentName = context.Entry(unicorn).Property(u => u.Name).CurrentValue;
                   var nameIsModified = context.Entry(unicorn).Property(u => u.Name).IsModified;
                   Console.WriteLine("Original: {0}", originalName);
                   Console.WriteLine("Current: {0}", currentName);
                   Console.WriteLine(nameIsModified);
    
                   context.Entry(unicorn).Property(u => u.Name).CurrentValue = newName;
                   currentName = context.Entry(unicorn).Property(u => u.Name).CurrentValue;
                   nameIsModified = context.Entry(unicorn).Property(u => u.Name).IsModified;
                   Console.WriteLine("Current: {0}", currentName);
                   Console.WriteLine(nameIsModified);
    
                   // ***** Setting OriginalValue to CurrentValue Fails *****
                   context.Entry(unicorn).Property(u => u.Name).OriginalValue = newName;
                   originalName = context.Entry(unicorn).Property(u => u.Name).OriginalValue;
                   nameIsModified = context.Entry(unicorn).Property(u => u.Name).IsModified;
                   Console.WriteLine("Original: {0}", currentName);
                   Console.WriteLine(nameIsModified);
    
                   // ***** Setting CurrentValue to OriginalValue Fails *****
                   //context.Entry(unicorn).Property(u => u.Name).CurrentValue = originalName;
                   //currentName = context.Entry(unicorn).Property(u => u.Name).CurrentValue;
                   //nameIsModified = context.Entry(unicorn).Property(u => u.Name).IsModified;
                   //Console.WriteLine("Current: {0}", currentName);
                   //Console.WriteLine(nameIsModified);
    
    }
    

     




    • Changed type Mark Phillips Saturday, September 24, 2011 5:43 PM
    • Edited by Mark Phillips Friday, September 30, 2011 1:45 PM Initial description of problem was incorrect
    Thursday, September 22, 2011 10:27 PM

All replies

  • i simulated this like you provided, but it looks ok.
    using (var context = new UnicornsContext())
    {
        // Create an entity that is not being tracked
        var unicorn = new Unicorn { Name = "Franky" };
    
        // Read and set the current value of Name as before
        var currentName1 = context.Entry(unicorn).Property(u => u.Name).CurrentValue;
        context.Entry(unicorn).Property(u => u.Name).CurrentValue = "Franky";
        var currentName2 = context.Entry(unicorn).Property("Name").CurrentValue;
        context.Entry(unicorn).Property("Name").CurrentValue = "Squeaky";
    }
    
    using (var context = new UnicornsContext())
    {
        var unicorn = context.Unicorns.Find(1);
    
        var nameIsModified1 = context.Entry(unicorn).Property(u => u.Name).IsModified;
    
        // Use a string for the property name
        var nameIsModified2 = context.Entry(unicorn).Property("Name").IsModified;
    }
    

    Everything was overlooked by me?

    Thanks,

    Werewolf,


    Just a newbie for everything.
    Monday, September 26, 2011 7:43 AM
  • Werewolf,

    In the case of your code, you have created two contexts.  Each context is independent of each other. The inital code I posted was intended to infer a single context.  I have now included the creation of the context within that code for clarification. 

    Thanks

    Mark

    Monday, September 26, 2011 12:26 PM
  • Hello Mark,

    Could you please send your demo application to me? My Mailbox: v-xugong@microsoft.com

    Thanks,


    Larcolais Gong[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.

    Thursday, September 29, 2011 2:09 PM
  • Hello, Mark.

    In my case it works fine as well.

    private static void DoIt()
    {
    	using (var db = new MyContext())
    	{
    		var data = db.SomeDatas.Find(1);
    		PrintState(db, data, "Initial Status");
    
    		db.Entry(data).Property(p => p.Name).CurrentValue = "newdata";
    		PrintState(db, data, "Current Value changed");
    
    		db.Entry(data).Property(p => p.Name).OriginalValue = "newdata";
    		PrintState(db, data, "Original Value changed");
    
    		db.Entry(data).Property(p => p.Name).CurrentValue = "olddata";
    		db.Entry(data).Property(p => p.Name).OriginalValue = "olddata";
    		PrintState(db, data, "Current & Original Values set to Initial state");
    	}
    }
    
    private static void PrintState(MyContext db, SomeData data, string headerText)
    {
    	Console.WriteLine(string.Format("------{0}------", headerText));
    	Console.WriteLine("Current: " + db.Entry(data).Property(p => p.Name).CurrentValue);
    	Console.WriteLine("Original: " + db.Entry(data).Property(p => p.Name).OriginalValue);
    	Console.WriteLine("IsModified: " + db.Entry(data).Property(p => p.Name).IsModified);
    	Console.WriteLine();
    }
    
    


    Here is an output:

     

     

    Thursday, September 29, 2011 8:04 PM
  • Rustam,

    The point I am trying to make is that if OriginalValue matches CurrentValue, IsModified should be false.  For example,  if I change the CurrentValue and then change it back to it's OriginalValue, I think that IsModified should return false.

    In addition, I question whether OriginalValue should ever be editable in the first place.  This allows for changing the OriginalValue to match the CurrentValue.  Allowing OriginalValue to be modified appears to explain why the first example listed above has to return true even though the OriginalValue and CurrentValue match.

    Of course, the workaround is that the IsModifed property is also editable.  So it can be set to true or false programatically.

    But would any of this be necessary if OriginalValue was not editable?

    Perhaps, I am unaware of a common scenario where OriginalValue would be edited.  Perhaps this functionality was created only for edge cases.  The result is that it has complicated what I think is by far the most common scenario.

     

    Regards,
    Mark

     

    Friday, September 30, 2011 1:31 PM
  • Hello, Mark.

    I am agree with your thoughts on OriginalValue should not be editable.

    As of "classic" entity framework (with using ObjectContext), the exposed values in ObjectStateManager.OriginalValues property are not editable.

    Regards

     

    Sunday, October 9, 2011 7:25 PM