如何在EntityFramework的ModelContext中泛型遍历并检测模型属性
泛型检测EF模型中指定属性的实现方案
方案一:反射+动态查询库(快速实现)
直接通过反射在运行时检查属性是否存在,结合System.Linq.Dynamic.Core库构建动态查询,无需硬编码每个模型。
- 先安装
System.Linq.Dynamic.CoreNuGet包 - 编写通用扩展方法:
using System; using System.Linq; using System.Reflection; using System.Linq.Dynamic.Core; public static class DbContextExtensions { public static IQueryable<T> QueryByProperty<T>(this DbContext context, string propertyName, object propertyValue) where T : class { var entityType = typeof(T); var property = entityType.GetProperty(propertyName, BindingFlags.Public | BindingFlags.Instance); if (property == null) { throw new ArgumentException($"实体 {entityType.Name} 不存在属性 {propertyName}"); } return context.Set<T>().Where($"{propertyName} == @0", propertyValue); } }
- 使用示例:
using (var context = new MyDbContext()) { // 查询Students表中objid=1234的数据 var students = context.QueryByProperty<Students>("objid", 1234).ToList(); // 复用方法查询其他带objid的表 var teachers = context.QueryByProperty<Teachers>("objid", 5678).ToList(); }
方案二:标记接口+T4模板改造(优雅持久化)
如果数据库中带objid的表是固定的,可以通过修改EF生成模型的T4模板,让这类模型自动实现标记接口,后续直接通过接口约束处理。
- 定义标记接口:
public interface IHasObjId { int objid { get; set; } }
- 找到EF生成模型的
Model.tt模板,修改类定义逻辑,当模型包含objid属性时自动继承接口:
<#=Accessibility.ForType(entityType)#> partial class <#=code.Escape(entityType)#> <#=entityType.BaseType != null ? " : " + code.Escape(entityType.BaseType) : ""#> <#=entityType.Properties.Any(p => p.Name.Equals("objid", StringComparison.OrdinalIgnoreCase)) ? ", IHasObjId" : ""#> { // 模板原有类内容 }
- 重新执行
Scaffold-DbContext生成模型,所有带objid的模型会自动实现IHasObjId - 编写强类型通用方法:
public static IQueryable<T> QueryByObjId<T>(this DbContext context, int objId) where T : class, IHasObjId { return context.Set<T>().Where(t => t.objid == objId); }
- 使用示例:
using (var context = new MyDbContext()) { var students = context.QueryByObjId<Students>(1234).ToList(); }
方案三:手动构建表达式树(无第三方依赖)
如果不想引入外部库,可以手动构建表达式树实现动态查询:
using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; public static class DbContextExtensions { public static IQueryable<T> QueryByProperty<T>(this DbContext context, string propertyName, object propertyValue) where T : class { var param = Expression.Parameter(typeof(T), "t"); var propertyExpr = Expression.Property(param, propertyName); var constantExpr = Expression.Constant(propertyValue, propertyExpr.Type); var equalExpr = Expression.Equal(propertyExpr, constantExpr); var lambda = Expression.Lambda<Func<T, bool>>(equalExpr, param); return context.Set<T>().Where(lambda); } }
内容的提问来源于stack exchange,提问作者EricaC
相关产品推荐
相关产品推荐

