如何获取DbContext中泛型类型T为变量的DbSet<T>实例?
动态获取DbContext中泛型DbSet的实现方案
刚好碰到过类似的场景,我来给你拆解一下怎么实现。你的核心需求就是:根据动态的实体类型(也就是继承自BaseClass的Class1、Class2这些),从MyDbContext实例里拿到对应的DbSet
下面给你两种常用的实现思路,按需选就行:
1. 直接利用DbContext内置的Set方法(简单快捷)
DbContext本身就提供了获取DbSet的方法,分两种情况:
如果你已经有实体实例
比如从XmlNode的CreateEntity()方法创建出了实体对象,直接用这个实例的类型来获取DbSet:
using var dbContext = new MyDbContext(); // 从字典拿到对应的XmlNode if (Nodes.TryGetValue("Tag1", out var targetNode)) { BaseClass entity = targetNode.CreateEntity(); // 获取对应的DbSet(返回非泛型DbSet类型) var dbSet = dbContext.Set(entity.GetType()); // 直接操作,比如添加实体 dbSet.Add(entity); dbContext.SaveChanges(); }
如果你只有Type对象(没有实例)
比如你提前知道了要操作的实体类型,就用反射调用泛型版本的Set方法:
public object GetTargetDbSet(MyDbContext dbContext, Type entityType) { // 获取DbContext的泛型Set方法,传入实体类型 var setMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set)) .MakeGenericMethod(entityType); // 调用方法获取DbSet return setMethod.Invoke(dbContext, null); }
要是需要强类型的DbSet
public DbSet<T> GetTypedDbSet<T>(MyDbContext dbContext) where T : BaseClass { return dbContext.Set<T>(); }
2. 提前缓存DbSet映射(高效复用)
如果你的DbContext结构固定,不想每次都用反射开销,可以提前把实体类型和对应的DbSet属性缓存起来,后续直接取用:
// 静态缓存字典,存储实体类型到DbSet属性的映射 private static readonly Dictionary<Type, PropertyInfo> _dbSetPropertyMap = new(); // 静态构造函数初始化缓存 static YourHelperClass() { var dbSetGenericType = typeof(DbSet<>); // 遍历MyDbContext的所有公开实例属性 var dbContextProperties = typeof(MyDbContext).GetProperties( BindingFlags.Public | BindingFlags.Instance); foreach (var prop in dbContextProperties) { var propType = prop.PropertyType; // 判断属性是否是DbSet<>的泛型实例,且实体类型继承自BaseClass if (propType.IsGenericType && propType.GetGenericTypeDefinition() == dbSetGenericType) { var entityType = propType.GetGenericArguments()[0]; if (typeof(BaseClass).IsAssignableFrom(entityType)) { _dbSetPropertyMap.Add(entityType, prop); } } } } // 获取DbSet的方法 public object GetCachedDbSet(MyDbContext dbContext, Type entityType) { if (_dbSetPropertyMap.TryGetValue(entityType, out var dbSetProp)) { return dbSetProp.GetValue(dbContext); } throw new ArgumentException($"未找到对应类型 {entityType.Name} 的DbSet"); }
这种方式第一次初始化后,后续获取DbSet的速度会快很多,适合频繁调用的场景。
内容的提问来源于stack exchange,提问作者Никита Львов
相关产品推荐
相关产品推荐

