如何对Dapper返回的对象自动执行AcceptChanges后续处理?
解决方案
方案一:全局钩子(推荐)
Dapper提供了静态的SqlMapper.OnMaterialized事件,可全局注册对象实例化后的处理逻辑,无需修改现有查询代码,完全满足“默认生效”的需求。
在应用启动阶段(比如Program.cs或Startup.cs的初始化逻辑中)添加以下代码:
using Dapper; using System.ComponentModel; // 全局注册对象实例化后的处理逻辑 SqlMapper.OnMaterialized += obj => { if (obj is IChangeTracking ict) { ict.AcceptChanges(); } };
注册后,所有通过Dapper反序列化生成的对象,只要实现了IChangeTracking接口,都会自动执行AcceptChanges()方法,完全透明无侵入。
注意事项:
- 该事件是静态全局事件,只需注册一次,重复注册会导致逻辑多次执行;
- 触发时机是对象属性映射完成之后,确保处理逻辑基于完整的实例数据。
方案二:扩展方法(按需启用)
如果不想全局生效,可通过扩展方法包装Dapper的查询方法,手动选择需要启用跟踪处理的查询:
using Dapper; using System.ComponentModel; using System.Data; using System.Threading.Tasks; public static class DapperTrackingExtensions { public static async Task<IEnumerable<T>> QueryWithTrackingAsync<T>( this IDbConnection conn, string sql, object param = null, IDbTransaction transaction = null, int? commandTimeout = null, CommandType? commandType = null) { var results = await conn.QueryAsync<T>(sql, param, transaction, commandTimeout, commandType); foreach (var item in results) { if (item is IChangeTracking ict) { ict.AcceptChanges(); } } return results; } }
使用时替换原有的QueryAsync调用即可:
var persons = await conn.QueryWithTrackingAsync<Models.User>("Select * from [User]"); var companies = await conn.QueryWithTrackingAsync<Models.Company>("Select * from [Company]");
内容的提问来源于stack exchange,提问作者Infarch
相关产品推荐
相关产品推荐

