I have a WCF server application running Entity Framework 6.
My client application consumes OData from the server via a DataServiceContext, and in my client code I want to be able to call a HasChanges() method on the context to see if any data in it has changed.
I tried using the following extension method:
public static bool HasChanges(this DataServiceContext ctx)
{
// Return true if any Entities or links have changes
return ctx.Entities.Any(ed => ed.State != EntityStates.Unchanged) || ctx.Links.Any(ld => ld.State != EntityStates.Unchanged);
}
But it always returns false, even if an entity it is tracking does have changes.
For instance, given that I have a tracked entity named Customer, the following code always returns before calling SaveChanges().
Customer.Address1 = "Fred"
if not ctx.HasChanges() then return
ctx.UpdateObject(Customer)
ctx.SaveChanges()
If I comment out the if not ctx.HasChanges() then return line of code, the changes are saved successfully so I'm happy that the entity has received the change and is able to save it.
It seems that the change is getting tracked by the context, just that I can't determine that fact from my code.
Can anyone tell me how to determine HasChanges on a DataServiceContext?
Far out. I just read through
DataServiceContext.UpdateObjectInternal(entity, failIfNotUnchanged), which is called directly fromUpdateObject(entity)with afalseargument.The logic reads like:
failIfNotUnchanged; (true only fromChangeState())So by the looks of it,
UpdateObjectdoesn't care about/check the internal state of the entity, just theStateenum. This makes updates feel a little inaccurate when there are no changes.However, I think your problem is then in the OP 2nd block of code, you check your extension
HasChangesbefore callingUpdateObject. The entities are only glorified POCOs (as you can read in yourReference.cs(Show Hidden Files, then under the Service Reference)). They have the obvious properties and a fewOn-operations to notify about changing. What they do not do internally is track state. In fact, there is anEntityDescriptorassociated to the entity, which is responsible for state-tracking inEntityTracker.TryGetEntityDescriptor(entity).Bottom line is operations actually work very simply, and I think you just need to make your code like
Though as we know now, this will always report HasChanges == true, so you may as well skip the check.
But don't despair! The partial classes provided by your service reference may be extended to do exactly what you want. It's totally boilerplate code, so you may want to write a .tt or some other codegen. Regardless, just tweak this to your entities:
But now this works great and is similarly expressive to the OP:
HTH!