Reputation: 4610
i'm using EF 4.3.1, I've overridden the SaveChanges() on the context so that I can get a list of the objects and their states and create entries in my audit log table. I need to store the id of the record in the audit log table so i have a reference to it. This is a problem when records are inserted, as I don't have access to the id before it's saved. Is there any way of getting the id at that point?
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
var objectStateManager = ((IObjectContextAdapter)this).ObjectContext.ObjectStateManager;
var modifiedAuditableEntities = objectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added).Where(e => (IAuditable)e.Entity != null);
foreach (var entry in modifiedAuditableEntities)
{
var entity = (IAuditable)entry.Entity;
if (entity != null)
{
switch (entry.State)
{
case EntityState.Added:
entity.IsAdded = true;
break;
case EntityState.Deleted:
entity.IsDeleted = true;
break;
case EntityState.Modified:
entity.IsModified = true;
break;
}
this.EntitySet<AuditLogEntry>().Add(this.auditLogService.CreateAuditLogEntryForEntity((IAuditable)entry.Entity));
}
return base.SaveChanges();
}
Upvotes: 2
Views: 3956
Reputation: 10416
If your goal is that you want both your save, and your audit log to be created at the same time, you could wrap it in a transaction scope so your method to be atomic.
public override int SaveChanges()
{
ChangeTracker.DetectChanges();
using (var scope = new TransactionScope())
{
var objectStateManager = ((IObjectContextAdapter) this).ObjectContext.ObjectStateManager;
var modifiedAuditableEntities =
objectStateManager.GetObjectStateEntries(EntityState.Modified | EntityState.Added).Where(
e => (IAuditable) e.Entity != null);
var result = base.SaveChanges();
foreach (var entry in modifiedAuditableEntities)
{
var entity = (IAuditable) entry.Entity;
if (entity != null)
{
switch (entry.State)
{
case EntityState.Added:
entity.IsAdded = true;
break;
case EntityState.Deleted:
entity.IsDeleted = true;
break;
case EntityState.Modified:
entity.IsModified = true;
break;
}
this.EntitySet<AuditLogEntry>().Add(
this.auditLogService.CreateAuditLogEntryForEntity((IAuditable) entry.Entity));
}
}
base.SaveChanges();
scope.Complete();
return result;
}
}
Upvotes: 5
Reputation: 51504
I would recommend using a stored procedure at the database level to perform your insert/auditing functions (and other database changes), and revoking the insert/update/delete permission from your users. As such you can guarantee the integrity of the update process and of the audit table.
Upvotes: 1
Reputation: 2743
Id the Id is an integer generated by the database there isnt any way of getting it before calling save changes. Possible solutions include:
Upvotes: 2