






















手写一个简化版DbExecutor,支持Query<T>(string sql, object parameters),将DataTable映射到T属性(支持Dapper风格的匿名参数)。
· 考察点:反射/Emit/表达式树性能对比、缓存映射逻辑、IDbCommand参数化注入。
public class DbExecutor { private readonly string _connectionString; // 缓存类型映射委托,避免频繁反射 private readonly ConcurrentDictionary<Type, Func<IDataRecord, object>> _mapperCache; public DbExecutor(string connectionString) { _connectionString = connectionString; _mapperCache = new ConcurrentDictionary<Type, Func<IDataRecord, object>>(); } // 执行查询,返回T类型列表 public async Task<List<T>> QueryAsync<T>(string sql, object parameters = null) { var result = new List<T>(); // 获取类型映射委托(缓存,避免重复反射) var mapper = _mapperCache.GetOrAdd(typeof(T), CreateMapper<T>); using var connection = new SqlConnection(_connectionString); await connection.OpenAsync(); // 处理参数 using var command = new SqlCommand(sql, connection); if (parameters != null) { // 反射获取参数对象的属性,添加到SqlCommand var paramProperties = parameters.GetType().GetProperties(); foreach (var prop in paramProperties) { var value = prop.GetValue(parameters) ?? DBNull.Value; command.Parameters.AddWithValue($"@{prop.Name}", value); } } // 执行查询,映射结果 using var reader = await command.ExecuteReaderAsync(); while (await reader.ReadAsync()) { var item = (T)mapper(reader); result.Add(item); } return result; } // 创建类型映射委托(使用Expression树,提升性能) private Func<IDataRecord, object> CreateMapper<T>(Type type) { // 创建参数(IDataRecord) var parameter = Expression.Parameter(typeof(IDataRecord), "record"); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); var bindings = new List<MemberBinding>(); foreach (var prop in properties) { // 获取列名(支持[Column]特性,无特性则使用属性名) var columnAttr = prop.GetCustomAttribute<ColumnAttribute>(); var columnName = columnAttr?.Name ?? prop.Name; // 表达式:record[columnName] var indexExpr = Expression.Property(parameter, "Item", Expression.Constant(columnName)); // 转换类型(将object转换为属性类型) var convertExpr = Expression.Convert(indexExpr, prop.PropertyType); // 绑定到属性 var binding = Expression.Bind(prop, convertExpr); bindings.Add(binding); } // 表达式:new T { Prop1 = ..., Prop2 = ... } var newExpr = Expression.New(type); var initExpr = Expression.MemberInit(newExpr, bindings); // 转换为object var convertToObject = Expression.Convert(initExpr, typeof(object)); // 编译为委托 return Expression.Lambda<Func<IDataRecord, object>>(convertToObject, parameter).Compile(); } } // 辅助特性:用于指定数据库列名 [AttributeUsage(AttributeTargets.Property)] public class ColumnAttribute : Attribute { public string Name { get; } public ColumnAttribute(string name) { Name = name; } }
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。