EF动态注册表映射DbSet时提示类型未纳入上下文模型求助
你遇到的报错核心原因有两个常见可能:
GetTbl<T>方法中调用的带字符串参数的DbContext.Set重载,作用是查询已注册实体对应的指定名称表的数据集,本身不负责实体类型的注册,只有类型已经被纳入上下文模型时才能正常调用- 你调用
GetTbl<T>()时传入的泛型参数T,和GetDynTypes()方法返回的类型不是同一个Type实例(常见于动态加载外部程序集的场景,同名类型属于不同的加载上下文/程序集版本)
修正方案
1. 修正GetTbl方法实现
替换原有的反射调用逻辑,改用无参数的Set重载获取对应类型的数据集,同时改用线程安全的类型字典做缓存避免频繁反射:
public abstract class DynamicDbContext : DbContext { private ConcurrentDictionary<Type, object> m_dbSets; public DynamicDbContext([NotNull] DbContextOptions options) : base(options) { } public DbSet<T> GetTbl<T>() where T : class { // 初始化DbSet缓存 if (m_dbSets == null) { m_dbSets = new ConcurrentDictionary<Type, object>(); var dynTypes = GetDynTypes(); foreach (var type in dynTypes) { var setMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set), Type.EmptyTypes); var dbSet = setMethod.MakeGenericMethod(type).Invoke(this, null); m_dbSets.TryAdd(type, dbSet); } } // 提前校验类型注册状态 if (!m_dbSets.TryGetValue(typeof(T), out var set)) { throw new InvalidOperationException($"类型 {typeof(T).FullName} 未注册到当前上下文"); } return (DbSet<T>)set; } protected abstract List<Type> GetDynTypes(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); var dynTypes = GetDynTypes(); foreach (var iter in dynTypes) { EntityTypeBuilder builder = modelBuilder.Entity(iter); builder.ToTable(iter.Name); } } }
2. 校验类型一致性
如果修改后仍有报错,需要确认以下两点:
- 派生类实现
GetDynTypes()返回的类型集合,确实包含你调用GetTbl<T>()时传入的T类型 - 两个场景下的类型是完全相同的
Type实例:可以通过对比typeof(T).AssemblyQualifiedName和GetDynTypes()返回对应类型的AssemblyQualifiedName验证,确保程序集名称、版本、公钥令牌完全一致
额外注意事项
不要在OnModelCreating执行完成前调用GetTbl方法,EF Core的模型构建完成前所有获取DbSet的操作都会抛出类型未注册的异常。
内容的提问来源于stack exchange,提问作者Csaba
相关产品推荐
相关产品推荐

