EF 4.0 POCO magic doesn't work-- No changes detected
I can't seem to update my database from disconnected poco objects. In this example, I fetch an ApplicationUser object, update varchar(100) field SSOID, but no changes take effect. Even when I refetch the object in the save method, nothing gets sent to the db.
If I try to call ApplyCurrentValues, it throws
An object with a key that matches the key of the supplied object could not be found in the ObjectStateManager. Verify that the key values of the supplied object match the key values of the object to which changes must be applied.
public void Save(ApplicationUser au)
{
ApplicationUser original = context.ApplicationUsers.FirstorDefault(a => a.UserID == au.UserID);
context.ContextOptions.ProxyCreationEnabled = false; //changing this has no effect
if(original == null)
{
context.AddObject("ApplicationUsers",au); //this works!
}
else
{
///let's manually set some properties on the object I just fetched.
original.SSOID = au.SSOID;
ObjectStateEntry entry = null;
context.DetectChanges();
context.ObjectStateManager.TryGetObjectStateEntry(original.EntityKey, out entry);
//entry is still null!
context.ApplicationUsers.ApplyCurrentValues(original); //BOOM!!
}
context.SaveChanges();
return;
}
I tried everything I can think of, even making ApplicationUser
implement System.Data.Objects.DataClasses.IEntityWithKey
, which supposedly isn't necessary.
Here's the mapping:
<EntitySetMapping Name="ApplicationUsers">
<EntityTypeMapping TypeName="MyCompanyName.ApplicationUser">
<MappingFragment StoreEntitySet="ApplicationUser">
<ScalarProperty Name="UserID" ColumnName="UserID" />
<ScalarProperty Name="SystemID" ColumnName="SystemID" />
<ScalarProperty Name="Username" ColumnName="Username" />
<!--snip-->
<ScalarProperty Name="CreatedOn" ColumnName="CreatedOn" />
<ScalarProperty Name="CreatedBy" ColumnName="CreatedBy" />
<ScalarProperty Name="开发者_StackOverflow社区SSOID" ColumnName="SSOID" />
</MappingFragment>
</EntityTypeMapping>
</EntitySetMapping>
Are you using the straight/simple POCO T4 template, or the self-tracking entities template??
The straight POCO have no support for any change tracking whatsoever - if you want that, you need the self-tracking entities.
See resources:
- Using Self Tracking Entities to retrieve and update
- Working with Self-Tracking Entities
Update: I think you are quite close to the right way of doing things here. You re-load the original state of the object (I would probably add a check on a timestamp or something to make sure the object in store hasn't been changed in the meantime).
Once you've done that, I believe you just need to detect yourself what changes have happened / where differences exist between au
and original
; update the original
accordingly, and then just simply call context.SaveChanges()
.
As far as I understand it, the .DetectChanges()
can't work, since you're using straight POCO classes without any change tracking, e.g. your au
object doesn't have any way of knowing what's been changed - you basically need to do a property-by-property comparison yourself.
精彩评论