EF泛型查询中如何通过表名动态创建实体传入Set<TEntity>
动态根据表名获取EF DbSet的解决方案
看你遇到的这个需求——根据页面传入的表名动态对应实体类,不用手动强转就能使用EF的Set<TEntity>,这里给你两个靠谱的实现思路:
思路1:直接用EF的非泛型Set方法(最省心)
EF的DbContext本身就提供了非泛型的Set(Type)方法,直接传实体类型就能拿到对应的DbSet,完全不用手动强转,这是最直接的方案。
步骤拆解:
- 先搞定表名和实体类型的映射(毕竟实体类名和数据库表名可能不一样,比如实体叫
SysUser,表名是sys_user) - 根据传进来的
tableName找到对应的实体Type - 调用非泛型
Set方法拿DbSet,接着就能执行查询了
代码示例:
public static void CreateInstance() { using (var ru = new RepositoryUse()) { // 页面传过来的表名 string tableName = "SysUser"; // 1. 建立表名-实体类型映射(可以抽成配置类,或者后面用自动扫描) var tableEntityMap = new Dictionary<string, Type> { { "SysUser", typeof(SysUser) }, { "SysRole", typeof(SysRole) } // 其他表的映射... }; // 2. 根据表名找对应的实体类型 if (tableEntityMap.TryGetValue(tableName, out var entityType)) { // 3. 用非泛型Set方法获取DbSet var dbSet = ru.Context.Set(entityType); // 执行自定义SQL,返回的是IEnumerable<object>,后续可以用反射处理 var queryResult = dbSet.FromSqlRaw($"select * from {tableName}").ToList(); // 举个例子:用反射获取实体的Id属性值 foreach (var item in queryResult) { var idProp = entityType.GetProperty("Id"); var idValue = idProp?.GetValue(item); // 这里可以加你的业务逻辑... } } } }
思路2:通过反射调用泛型Set<T>方法
如果你一定要用泛型版本的Set<T>,可以通过反射动态创建并调用泛型方法,同样能避免手动强转。
代码示例:
public static void CreateInstance() { using (var ru = new RepositoryUse()) { string tableName = "SysUser"; var tableEntityMap = new Dictionary<string, Type> { { "SysUser", typeof(SysUser) } }; if (tableEntityMap.TryGetValue(tableName, out var entityType)) { // 1. 获取DbContext的Set<T>泛型方法 var setMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set))!.MakeGenericMethod(entityType); // 2. 调用方法拿到泛型DbSet<T> var dbSet = setMethod.Invoke(ru.Context, null); // 3. 反射调用FromSqlRaw(因为它也是泛型方法) var fromSqlMethod = typeof(RelationalQueryableExtensions).GetMethod(nameof(RelationalQueryableExtensions.FromSqlRaw))! .MakeGenericMethod(entityType); var query = fromSqlMethod.Invoke(null, new object[] { dbSet, $"select * from {tableName}" }) as IQueryable; var resultList = query?.ToList(); } } }
优化小技巧:自动扫描实体类与表名映射
上面手动写字典太麻烦,你可以用特性+程序集扫描自动生成映射:
- 给实体类标记
TableAttribute:
[Table("SysUser")] public class SysUser { // 实体属性... }
- 扫描程序集里的实体类,自动构建映射:
// 扫描当前程序集里所有带TableAttribute的实体类 var tableEntityMap = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => t.GetCustomAttribute<TableAttribute>() != null) .ToDictionary( t => t.GetCustomAttribute<TableAttribute>()!.Name, t => t );
这样新增实体类后,不用手动维护字典,自动就能加入映射啦。
内容的提问来源于stack exchange,提问作者netnr
相关产品推荐
相关产品推荐

