Using Entity Framework 5, Given an object messenger
that exists in the database, with bit property published
, in previous versions of EF I would update it like this:
using (var c = new EFContext())
{
Data.Messenger cm = new Messenger { MessageId = messageId };
c.Messengers.Attach(cm);
cm.Published = newPublishedValue;
c.SaveChanges();
}
However, using EF5, this works if newPublishedValue
is true
, but if newPublishedValue
is false
, no changes are made to the database. Likewise, this pattern will not set integer values to 0.
What's going on here?
Replacing
c.Messengers.Attach(cm);
with
c.Entry(cm).State = System.Data.EntityState.Modified;
Fixes the issue, but if EF5 won't update properties of my new Data.Messenger
that are of a default struct value, doesn't that render the Attach
method a bit useless?
What am I missing here?
It only worked in previous versions probably when you have used entities derived from EntityObject
or POCOs with dynamic proxy change tracking. In that case the property setter is overridden with code that sets a Modified
flag for this property when you assign a value (= call the setter) no matter what the old value was.
Using POCOs without dynamic change tracking proxies it doesn't work - for no version of EF - because the property setter is just an assignment of a data field in the entity class. Change tracking happens by snapshot change tracking which means that EF compares the values of a snapshot of the entity taken when you call Attach
with the values the entity has when you call SaveChanges
. If the values didn't change EF detects no changes and doesn't write an UPDATE statement for the property.
Attach
is only for adding an entity to the context in Unchanged
state. In your case you have to mark the property as Modified
explicitly to ensure that it will be updated in the DB, no matter what the old value was:
c.Entry(cm).Property(x => x.Published).IsModified = true;