que tienen una clase base que heredar de que tiene dos cero a muchas relaciones con otras entidades:ChangeTracker Entity Framework 4.1 - Los valores originales de los objetos relacionados con
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; }
}
Estoy teniendo dificultades para obtener los valores originales de éstos relaciones (RelatedWebObjects & RelatedTags) cuando se observan las entidades que usan ChangeTracker durante SaveChanges. Puedo ver todos los valores escalares antes y después, y puedo ver las nuevas relaciones, pero no puedo ver las antiguas. Intenté usar los métodos Miembro y Colección, pero esos solo me muestran los valores actuales; no el viejo Además, no me gusta usarlos porque me obliga a conocer el nombre de la propiedad de navegación, que no es lo suficientemente genérica.
Puedo encontrar los objetos relacionados cuya relación está siendo modificada, pero por supuesto los valores dentro de esos objetos relacionados no están cambiando, por lo que tampoco sirve de nada.
¿Existe alguna manera limpia de rastrear las relaciones previas de una entidad durante SaveChanges con ChangeTracker?
A continuación se muestra la sección de código que estoy trabajando en:
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();
}
ObjectStateManager también está modificando los objetos relacionados y debería poder obtener las entradas de estado de objeto de la misma forma que lo hace para su objeto principal. Si publica el código con el que está luchando, podría ayudarlo. –
Gracias de nuevo Morteza ... Publiqué la sección de código con la que estoy trabajando ahora - por favor disculpen el descuido; no ha sido refactorado en absoluto, solo tratando de hacer que funcione. Puedo obtener las propiedades escalares de los objetos sin ningún problema usando las cadenas IEnumerable: entity.OriginalValues.PropertyNames & entity.CurrentValues.PropertyNames. Estoy teniendo problemas con entity.Collection() y entity.Member(). ¿Cuál debería usarse para lo que estoy tratando de lograr? ¿Hay alguna manera de hacer este genérico para que no tenga que codificar los nombres de las colecciones? Reflexión tal vez? – DMC
no estoy en posición de probar esto hasta mañana ... ¿alguno de ustedes sabe cómo puedo dividir puntos entre dos respuestas? porque creo que ambos dieron información muy valiosa. – DMC