如何通过字符串字段名动态构造EF Select表达式以泛型获取表主键值
解决方案
你需要通过手动构造表达式树生成Select方法需要的Lambda表达式,实现代码如下:
// 核心表达式构造逻辑,对应生成Lambda:e => (object)e.主键属性名 var parameter = Expression.Parameter(typeof(EntityType), "e"); var propertyAccess = Expression.Property(parameter, keyNames[0]); var convertToObject = Expression.Convert(propertyAccess, typeof(object)); var selector = Expression.Lambda<Func<EntityType, object>>(convertToObject, parameter);
修改后的完整GetKeyValue方法:
public object GetKeyValue(EntityType searchCriteria, ConnectionContext connectionContext) { IsContextValid(connectionContext); if (searchCriteria == null) throw new ArgumentException("", "searchCriteria"); List<string> keyNames = GetEntityPrimaryKeyName(searchCriteria, connectionContext); if (keyNames.Count <= 0) return null; // 构造属性选择表达式 var parameter = Expression.Parameter(typeof(EntityType), "e"); var propertyAccess = Expression.Property(parameter, keyNames[0]); var objectConversion = Expression.Convert(propertyAccess, typeof(object)); var keySelector = Expression.Lambda<Func<EntityType, object>>(objectConversion, parameter); using (var db = CreateDbContext<DbContextType>(connectionContext)) { return db.Set<EntityType>() .AsExpandable() .Where(SetupFindMany(searchCriteria, connectionContext)) .Select(keySelector) .FirstOrDefault(); } }
注意事项
Expression.Property会根据传入的属性名字符串匹配对应实体的属性,不需要硬编码属性名Expression.Convert是为了兼容值类型主键(比如int、Guid),把属性值装箱为object类型,保证返回值类型统一。如果确定主键都是字符串类型,可以去掉Convert步骤,直接生成Expression<Func<EntityType, string>>类型的表达式即可- 传入的主键名必须是实体类的属性名,而非数据库表的列名,否则会抛出属性不存在的异常
内容的提问来源于stack exchange,提问作者BWhite
相关产品推荐
相关产品推荐

