.NET实现字段变更记录
简介
有时候在开发中,需要对实体的某个字段做变更日志,如果显式保存日志,会对业务代码耦合太大。
本文采用重写DbContext的SaveChanges方法实现,在指定字段变更时,自动添加变更日志,减少对业务代码的耦合。
实体定义
ToDoItem是主实体,ToDoItemTextLog是ToDoItem的Text字段的变更记录
public class ToDoItem : FullAuditedEntity<long>
{
public string Text { get; set; }
}
public class ToDoItemTextLog : FullAuditedEntity<long>
{
public long ToDoItemId { get; set; }
[ForeignKey(nameof(ToDoItemId))]
public ToDoItem ToDoItem { get; set; }
public string NewValue { get; set; }//新值
public string OriginalValue { get; set; }//旧值
}
在项目的DbContext类中,增加一个方法
protected virtual ICollection<ToDoItemTextLog> ChangeToDoItemTextLog()
{
//获取跟踪的实体
var entries = ChangeTracker.Entries().ToList();
//定义数组
var logs = new List<ToDoItemTextLog>();
foreach (var entry in entries)
{
//如果该实体是ToDoItem,并且是被修改的状态
if (entry.Entity is ToDoItem toDoItem && entry.State == EntityState.Modified)
{
//获取Text字段的新旧值,并存入数组
//var properties = entry.Metadata.GetProperties();
var propEntry = entry.Property("Text");
logs.Add(new ToDoItemTextLog()
{
ToDoItemId = toDoItem.Id,
NewValue = propEntry.CurrentValue.ToString(),
OriginalValue = propEntry.OriginalValue.ToString(),
});
}
}
return logs;
}
重写DbContext的SaveChanges和SaveChangesAsync
保存变更记录数组的代码需要放在base.SaveChanges()之前
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
// ……其他本文无关代码
// 获取变更记录的数组
var toDoItemTextLogs = ChangeToDoItemTextLog();
if (toDoItemTextLogs.Count > 0)
// 开启事务
using (var tran = Database.BeginTransaction())
{
// 将该数组存入数据库
AddRange(toDoItemTextLogs);
tran.Commit();
}
// ……其他本文无关代码
}
public override async Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = new CancellationToken())
{
// ……其他本文无关代码
var toDoItemTextLogs = ChangeToDoItemTextLog();
if (toDoItemTextLogs.Count > 0)
using (var tran = await Database.BeginTransactionAsync(cancellationToken))
{
AddRange(toDoItemTextLogs);
await tran.CommitAsync(cancellationToken);
}
// ……其他本文无关代码
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构