开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜