Ho una classe base che ho ereditato da quella ha due zero a molti rapporti con altre entità:ChangeTracker Entity Framework 4.1 - I valori originali di oggetti correlati
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; }
}
Sto avendo difficoltà a ottenere i valori originali per questi relazioni (RelatedWebObjects & RelatedTags) quando si guardano le entità che utilizzano ChangeTracker durante SaveChanges. Posso vedere tutti i valori scalari prima e dopo, e posso vedere le nuove relazioni, ma non riesco a vedere quelle vecchie. Ho provato a utilizzare i metodi Member e Collection, ma solo quelli mostrano i valori correnti; non il vecchio. Inoltre non mi piace usare quelli perché mi richiede di conoscere il nome della proprietà di navigazione, che non è abbastanza generico.
Sono in grado di trovare gli oggetti correlati di cui si sta modificando la relazione, ma ovviamente i valori all'interno di tali oggetti correlati non cambiano, quindi neanche questo è di aiuto.
C'è qualche modo pulito per me per tenere traccia delle relazioni precedenti di un'entità durante SaveChanges con ChangeTracker?
Di seguito è la sezione di codice che sto lavorando su:
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();
}
Gli oggetti correlati vengono modificati anche dall'ObjectStateManager e si dovrebbe essere in grado di ottenere le voci dello stato dell'oggetto proprio come si ottiene per l'oggetto principale. Se pubblichi il codice con cui stai lottando, potrei essere in grado di aiutarti. –
Grazie ancora Morteza ... Ho postato la sezione di codice con cui sto lavorando in questo momento - per favore scusate la sciatteria di esso; non è stato affatto rifatto - solo cercando di farlo funzionare. È possibile ottenere le proprietà scalari degli oggetti senza problemi utilizzando le stringhe IEnumerable: entity.OriginalValues.PropertyNames e entity.CurrentValues.PropertyNames. Ho problemi con entity.Collection() e entity.Member(). Quale dovrebbe essere usato per quello che sto cercando di realizzare? C'è un modo per rendere questo generico in modo da non dover codificare i nomi delle collezioni? Riflessione forse? – DMC
non sono in grado di provare questo fino a domani ... qualcuno di voi sa come posso dividere i punti tra due risposte? perché penso che entrambi abbiate dato informazioni preziose. – DMC