如果您只关心在应用程序添加/更新/删除记录时对此进行跟踪,那么您可以利用有界上下文在适用的 DbContext 的 SaveChanges 上执行此操作:
首先创建一个单独的 DbContext,该 DbContext 将为该存储过程调用提供服务或与所需实体交互以跟踪更改记录。创建对此 DbContext 的引用,作为您要跟踪实体更新的应用程序 DbContext 的一部分。
举个例子,一个 LoggingDbContext 和一个 AppDbContext:
public class LoggingDbContext : DbContext
{
// ...
}
public class AppDbContext : DbContext
{
private readonly LoggingDbContext _loggingDbContext = null;
public AppDbContext(string connectionString, LoggingDbContext loggingDbContext)
: base(connectionString)
{
_loggingDbContext = loggingDbContext ?? throw new ArgumentNullException("loggingDbContext");
}
public override int SaveChanges()
{
// Do your logging call...
var log = new Log { Message = "SaveChanges Called!" };
_loggingDbContext.Logs.Add(log);
_loggingDbContext.SaveChanges();
return base.SaveChanges();
}
}
OnSaveChanges 覆盖可以调用您的存储过程或任何必要的。如果您想区分何时添加、删除实体等,您可以使用 ChangeTracker 检查特定更改类型或特定实体的更改:
var updatedCustomers = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Modified)
.Select(x => x.Entity)
.OfType<Customer>();
var insertedCustomers = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Added)
.Select(x => x.Entity)
.OfType<Customer>();
var deletedCustomers = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Deleted)
.Select(x => x.Entity)
.OfType<Customer>();
从那里您可以检查带有 .ToList() 或 .Select() 的实体以了解特定详细信息,或者只需执行 .Any() 或 .Count() 以评估是否添加/更新/删除了特定实体类型等。
我在我的 DbContexts 中将此模式用于跟踪 LastModifiedBy 用户/日期跟踪之类的模型。我有一个 CurrentUserLocator 用于解析会话的当前登录用户,然后是一个包含 CreatedBy/CreatedAt/LastModifiedBy/LastModifiedAt 字段的“可编辑”实体的基类。这样,当我的 DbContext 保存详细信息时,上下文 SaveChanges 看起来像这样:
// These DbContexts do not allow for hard Deletes.
if (ChangeTracker.Entries().Any(x => x.State == EntityState.Deleted))
throw new ApplicationException("Hard deletes are not supported.");
var currentUser = Users.Single(x => x.UserId == CurrentUserLocator.CurrentUserId);
var updatedEntities = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Modified)
.Select(x => x.Entity)
.Cast<EditableEntityBase>();
foreach (var entity in updatedEntities)
{
entity.LastModifiedBy = currentUser;
entity.LastModifiedAt = DateTime.Now;
}
var insertedEntities = ChangeTracker.Entries()
.Where(x => x.State == EntityState.Added)
.Select(x => x.Entity)
.Cast<EditableEntityBase>();
foreach (var entity in insertedEntities)
{
entity.CreatedBy = entity.LastModifiedBy = currentUser;
entity.CreatedAt = entity.LastModifiedAt = DateTime.Now;
}
return base.SaveChanges();
上下文还跟踪不可编辑的实体(查找等),因此这也有助于防止以某种方式插入或更新不可编辑的实体的情况。由于我的系统在此示例中使用软删除,因此它还可以防止硬删除实体。此方法可用于利用单独的 DbContext 调用存储过程或以其他方式修改其他实体等,而不会“绊倒”SaveChanges 中的那些更改跟踪挂钩。