I have a base class that I inherit from that has two zero to many relationships with other entities:
public abstract class WebObject
{
public WebObject()
{
RelatedTags = new List<Tag>();
RelatedWebObjects = new List<WebObject>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
[InverseProperty("WebObjects")]
public virtual WebSite WebSite { get; set; }
[Required(ErrorMessage = "Every WebObject must be associated with a WebSite.")]
public Guid WebSiteId { get; set; }
public virtual ICollection<Tag> RelatedTags { get; set; }
public IList<Guid> RelatedTagIds { get; set; }
public virtual ICollection<WebObject> RelatedWebObjects { get; set; }
public IList<Guid> RelatedWebObjectIds { get; set; }
}
I am having difficulty getting the original values for these relationships (RelatedWebObjects & RelatedTags) when looking at the entities using ChangeTracker during SaveChanges. I can see all of the scalar values before and after, and I can see the new relationships, but I cannot see the old ones. I've tried using the Member and Collection methods, but those only show me the current values; not the old. Also I don't like using those because it requires me to know the name of the navigation property, which isn't generic enough.
I can find the related objects whose relationship is being changed, but of course the values within those related objects isn't changing, so that isn't any help either.
Is there some clean way for me to track the previous relationships of an entity during SaveChanges with ChangeTracker?
Below is the section of code that I'm working on:
public override int SaveChanges()
{
List<AuditObject> auditTrailList = new List<AuditObject>();
foreach (DbEntityEntry entity in ChangeTracker.Entries().Where(obj => { return obj.State == EntityState.Added || obj.State == EntityState.Modified || obj.State == EntityState.Deleted; }))
{
if (!(entity.Entity is AuditObject))
{
AuditObject auditObject = new AuditObject();
auditObject.Id = Guid.NewGuid();
auditObject.RevisionStamp = DateTime.Now;
auditObject.UserName = HttpContext.Current.User.Identity.Name;
auditObject.EntityType = Utilities.GetCleanClassNameIfProxyClass(entity.Entity.GetType().Name);
if (entity.State == EntityState.Added)
auditObject.Action = EntityState.Added.ToString();
else if (entity.State == EntityState.Modified)
auditObject.Action = EntityState.Modified.ToString();
else if (entity.State == EntityState.Deleted)
auditObject.Action = EntityState.Deleted.ToString();
DbMemberEntry t1 = entity.Member("RelatedWebObjects");
// cannot find original relationship collection...
DbCollectionEntry t2 = entity.Collection("RelatedWebObjects");
// cannot find original relationship collection...
if (entity.State == EntityState.Added || entity.State == EntityState.Modified)
{
XDocument currentValues = new XDocument(new XElement(auditObject.EntityType));
foreach (string propertyName in entity.CurrentValues.PropertyNames)
{
currentValues.Root.Add(new XElement(propertyName, entity.CurrentValues[propertyName]));
}
auditObject.NewData = Regex.Replace(currentValues.ToString(), @"\r\n+", " ");
}
if (entity.State == EntityState.Modified || entity.State == EntityState.Deleted)
{
XDocument originalValues = new XDocument(new XElement(auditObject.EntityType));
foreach (string propertyName in entity.OriginalValues.PropertyNames)
{
originalValues.Root.Add(new XElement(propertyName, entity.OriginalValues[propertyName]));
}
auditObject.OldData = Regex.Replace(originalValues.ToString(), @"\r\n+", " ");
}
auditTrailList.Add(auditObject);
}
}
foreach (var audit in auditTrailList)
this.AuditObjects.Add(audit);
return base.SaveChanges();
}