如何将字符串转为实体类以动态使用db.Set查询不同表?
动态调用EF Core的db.Set实现多表查询
核心思路
EF Core的DbContext.Set<T>有对应的非泛型重载Set(Type entityType),直接传入实体类型就能获取对应DbSet。我们只需要把字符串映射到对应的实体Type,就能摆脱if-else分支。
方法一:预定义类型映射字典(推荐)
提前维护字符串和实体类型的映射关系,避免频繁反射查找,性能更稳定:
// 全局维护实体类型映射(可放在DbContext或单独工具类中) private static readonly Dictionary<string, Type> _entityTypeMap = new Dictionary<string, Type> { {"User", typeof(User)}, {"Invoice", typeof(Invoice)}, {"Address", typeof(Address)}, {"Product", typeof(Product)} }; // 动态获取DbSet的方法 public IQueryable GetDynamicDbSet(DbContext db, string entityName) { if (_entityTypeMap.TryGetValue(entityName, out var entityType)) { return db.Set(entityType); } throw new ArgumentException($"不存在名为{entityName}的实体模型"); }
方法二:通过反射自动查找实体类型
如果实体类都在当前程序集,且命名严格匹配字符串,可以用反射自动查找:
public IQueryable GetDynamicDbSet(DbContext db, string entityName) { // 从当前程序集查找匹配名称的实体类型(忽略大小写) Type entityType = Assembly.GetExecutingAssembly().GetTypes() .FirstOrDefault(t => t.Name.Equals(entityName, StringComparison.OrdinalIgnoreCase)); if (entityType == null) { throw new ArgumentException($"找不到实体类型:{entityName}"); } return db.Set(entityType); }
动态查询扩展
拿到IQueryable后,如果需要执行动态条件查询,可以使用System.Linq.Dynamic.Core包(NuGet安装),支持字符串形式的Linq表达式:
// 示例:动态查询Id=123的记录 var dbSet = GetDynamicDbSet(db, "User"); var result = dbSet.Where("Id == @0", 123).ToList();
注意事项
- 实体名称映射要确保一致性,建议用常量或枚举替代硬编码字符串,减少错误
- 反射查找时,如果实体在其他程序集,需要替换为对应程序集(比如
Assembly.Load("YourEntityAssembly")) - 动态查询要使用参数化方式(如示例中的
@0),避免SQL注入风险
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

