Mam klasy bazowej że dziedziczą od tego ma dwa zera do wielu relacji z innymi podmiotami:ChangeTracker Entity Framework 4.1 - oryginalne wartości powiązanych obiektów
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; }
}
Mam trudności z oryginalnych wartości tych relacje (RelatedWebObjects & RelatedTags) podczas przeglądania obiektów używających ChangeTracker podczas SaveChanges. Widzę wszystkie wartości skalarne przed i po, i widzę nowe relacje, ale nie widzę starych. Próbowałem już używać metod członkowskich i kolekcji, ale te pokazują tylko bieżące wartości; nie stary. Również nie lubię ich używać, ponieważ wymaga to znajomości nazwy właściwości nawigacji, która nie jest generyczna.
Mogę znaleźć powiązane obiekty, których relacja jest zmieniana, ale oczywiście wartości w tych powiązanych obiektach się nie zmieniają, więc to też nie jest żadna pomoc.
Czy jest jakiś czysty sposób śledzić poprzednie relacje jednostki podczas SaveChanges z ChangeTracker?
Poniżej znajduje się fragment kodu, który pracuję nad:
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();
}
Obiekty pokrewne są również śledzone przez ObjectStateManager, a powinieneś być w stanie uzyskać ich wpisy stanu obiektu, podobnie jak otrzymujesz je dla głównego obiektu. Jeśli opublikujesz kod, z którym walczysz, być może będę mógł Ci pomóc. –
Jeszcze raz dziękuję Morteza ... Wysłałem sekcję kodu, nad którą teraz pracuję - proszę wybaczyć tę niechlujstwo; w ogóle nie został refaktoryzowany - po prostu próbując go uruchomić. Mogę uzyskać właściwości skalarne obiektów bez problemu za pomocą ciągów IEnumerable: entity.OriginalValues.PropertyNames & entity.CurrentValues.PropertyNames. Mam problem z entity.Collection() i entity.Member(). Który powinien być użyty do tego, co próbuję osiągnąć? Czy istnieje sposób na zrobienie tego generycznego, aby nie musieć sztywno kodować nazw kolekcji? Może refleksja? – DMC
Nie jestem w stanie wypróbować tego do jutra ... czy któreś z was wie, w jaki sposób mogę podzielić punkty pomiędzy dwie odpowiedzi? ponieważ uważam, że oboje przekazaliście bardzo cenne informacje. – DMC