Sé que hay varias publicaciones similares, pero no puedo encontrar ninguna con una solución a este problema.
Quiero agregar un (tipo de) AudioLog al agregar, cambiar o eliminar entidades (eliminación suave) en Entity Framework 6. He anulado SaveChanges y porque solo quiero agregar entradas de registro para EntityStates Added, Modified o Deleted, Traigo la lista antes de llamar a SaveChanges la primera vez. El problema es que, como necesito registrar qué operación se ha ejecutado, debo inspeccionar el EntityState de las entidades. Pero después de llamar a SaveChanges, EntityState permanece sin cambios para todas las entradas.
public override int SaveChanges()
{
using (var scope = new TransactionScope())
{
var modifiedEntries = ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Deleted || e.State == EntityState.Modified)
.ToList();
int changes = base.SaveChanges();
foreach (var entry in modifiedEntries)
{
ApplyAuditLog(entry);
}
base.SaveChanges();
scope.Complete();
return changes;
}
}
private void ApplyAuditLog(DbEntityEntry entry)
{
ILog entity = entry.Entity as ILog;
if (entity != null)
{
LogOperation operation;
switch (entry.State)
{
case EntityState.Added:
operation = LogOperation.CreateEntity;
break;
case EntityState.Deleted:
operation = LogOperation.DeleteEntity;
break;
case EntityState.Modified:
operation = LogOperation.UpdateEntity;
break;
default:
throw new ArgumentOutOfRangeException();
}
AuditLog log = new AuditLog
{
Created = DateTime.Now,
Entity = entry.Entity.GetType().Name,
EntityId = entity.Id,
Operation = operation,
};
AuditLog.Add(log);
}
}
Ahhh ... ¡¡Por supuesto !! La identificación solo será un "problema" para las entidades que se agregaron recientemente, por lo que al dividir la lista en dos (una para modificar / eliminar y otra para agregar), creo el AuditLog en dos etapas.
Para cualquier persona que quiera aplicar este tipo de AuditLog, aquí está mi código de trabajo:
public override int SaveChanges()
{
using (var scope = new TransactionScope())
{
var addedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Added).ToList();
var modifiedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted || e.State == EntityState.Modified).ToList();
foreach (var entry in modifiedEntries)
{
ApplyAuditLog(entry);
}
int changes = base.SaveChanges();
foreach (var entry in addedEntries)
{
ApplyAuditLog(entry, LogOperation.CreateEntity);
}
base.SaveChanges();
scope.Complete();
return changes;
}
}
private void ApplyAuditLog(DbEntityEntry entry)
{
LogOperation operation;
switch (entry.State)
{
case EntityState.Added:
operation = LogOperation.CreateEntity;
break;
case EntityState.Deleted:
operation = LogOperation.DeleteEntity;
break;
case EntityState.Modified:
operation = LogOperation.UpdateEntity;
break;
default:
throw new ArgumentOutOfRangeException();
}
ApplyAuditLog(entry, operation);
}
private void ApplyAuditLog(DbEntityEntry entry, LogOperation logOperation)
{
ILog entity = entry.Entity as ILog;
if (entity != null)
{
AuditLog log = new AuditLog
{
Created = DateTime.Now,
Entity = entry.Entity.GetType().Name,
EntityId = entity.Id,
Operation = logOperation,
};
AuditLog.Add(log);
}
}