in my DbContext subclass, I redefined the SaveChanges () method, so I can implement some sort of trigger-like functionality (before the changes are actually saved). Now in some of these triggers it is necessary to determine whether certain relationships have changed, regardless of many to many, one to one / zero, etc.
I read several posts on the Internet, including some on this site, which mention that the DbContext API does not provide any means to get relationship information. However, an ObjectContext should be able to.
My SaveChanges method:
public override int SaveChanges() { IEntity entity; ChangeTracker.DetectChanges(); var stateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager; var added = stateManager.GetObjectStateEntries(EntityState.Added).ToList(); var updated = stateManager.GetObjectStateEntries(EntityState.Modified).ToList(); var deleted = stateManager.GetObjectStateEntries(EntityState.Deleted).ToList(); var unchanged = stateManager.GetObjectStateEntries(EntityState.Unchanged).ToList(); while ((entity = _entitiesRequiringTriggering.FirstOrDefault(x => x.Value).Key) != null) { _entitiesRequiringTriggering[entity] = false; var entry = ChangeTracker.Entries<IEntity>().SingleOrDefault(x => x.State != EntityState.Unchanged && x.Entity == entity); if (entry == null) continue; var trigger = Triggers.Triggers.GetTriggerForEntity(entry.Entity, this); if (trigger == null) continue; trigger.BeforeSave(entry.Entity); switch (entry.State) { case EntityState.Added: trigger.BeforeAdd(entry.Entity); break; case EntityState.Modified: trigger.BeforeUpdate(entry.Entity); break; case EntityState.Deleted: trigger.BeforeDelete(entry.Entity); break; } } return base.SaveChanges(); }
Note the four variables added , updated , deleted, and unchanged . According to what I have found so far, GetObjectStateEntries should return an ObjectStateEntry collection that has the IsRelationship property.
I run the following code in a test application:
using (var db = container.Resolve<IDatabaseContext>()) { var cus = db.Query<Customer>().Single(x => x.Id == 1); var newAddress = db.Query<Address>().Single(x => x.Id == 5); cus.Address = newAddress;
When I check the code in SaveChanges after this call, I get the expected: one result in the updated list, the Customer object. But I never get an ObjectStateEntry for a one-to-one relationship Customer_Address.
I need to be able to detect, as described above, when relationships have changed. For normal scalar properties, you will do the following:
var changed = DbEntry.Property(x => x.Name).OriginalValue == DbEntry.Property(x => x.Name).CurrentValue;
But for reference properties that don't work explicitly. Any ideas?