EF手动/动态表注册

Posted

技术标签:

【中文标题】EF手动/动态表注册【英文标题】:EF manual/dynamic table registration 【发布时间】:2021-08-19 10:49:48 【问题描述】:

我正在尝试手动创建一些表并动态映射到DbSet,但它不起作用。这是我的DbContext 课程:

public abstract class DynamicDbContext : DbContext

    private List<IQueryable> m_dbSets;

    public DynamicDbContext([NotNull] DbContextOptions options) :
        base(options)
    
    

    public DbSet<T> GetTbl<T>() where T : class
    
        if (m_dbSets == null)
        
            m_dbSets = new List<IQueryable>();

            foreach (var iter in GetDynTypes())
            
                var setMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set), new[]  typeof(string) );
                IQueryable foundSet = (IQueryable)setMethod
                    .MakeGenericMethod(iter)
                    .Invoke(this, new object[]  iter.Name );

                    m_dbSets.Add(foundSet);
                
            
        

        return m_dbSets.FirstOrDefault(obj => obj.ElementType == typeof(T)) as DbSet<T>;
    
    
    protected abstract List<Type> GetDynTypes();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    
        base.OnModelCreating(modelBuilder);

        foreach (var iter in GetDynTypes())
        
            EntityTypeBuilder builder = modelBuilder.Entity(iter);
            builder.ToTable(iter.Name);
        
    
    #endregion

该类从应用程序的派生类中获取动态类型,并应将这些类作为表注册到数据库中。然后我想使用 Linq 来处理表格,所以我引入了 GetTbl 方法,该方法将返回 DbSet&lt;T&gt; 以便应用程序可以在此集合上调用 Linq。这个方法使用反射来获取DbSet,不过我也试过直接调用Set&lt;T&gt;(typeof(T).Name)

当我尝试访问返回的 DbSet 时,结果是异常: 无法为“Abc”创建 DbSet,因为该类型未包含在上下文模型中

看起来表是创建的,例如当我运行迁移命令时,我可以看到数据库中的表:

dotnet ef migrations add InitialCreate

问题可能在于表映射到DbSet - 在我的GetTbl 方法中。或者我可能需要在 OnModelCreating 方法中做一些额外的事情。

不确定是什么问题。任何帮助表示赞赏:-) 谢谢

【问题讨论】:

请看***.com/questions/38532764/… 这能回答你的问题吗? Create Tables on runtime in EF Core 不幸的是,这没有帮助。检查我的数据库,创建了表,但是我无法在我的 GetTbl 方法中动态地将表映射到 DbSet。 在 OnModelCreating 中注册类型后,只需 myDbContext.Set&lt;T&gt;(); 即可获取 DbSet 【参考方案1】:

在 OnModelCreating 中注册类型后,您可以简单地获取 DbSet

 myDbContext.Set<T>();

因此,更简单的设计是仅使用您在运行时专门针对动态实体类型的单个泛型类型。例如

public class DynamicDbContext<T> : DbContext where T:class

    public DynamicDbContext([NotNull] DbContextOptions options) :
        base(options)
    
    

    public DbSet<T> Entities => this.Set<T>();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    
        modelBuilder.Entity<T>().ToTable(typeof(T).Name);
        base.OnModelCreating(modelBuilder);
    

如果表不存在,当然不会创建表。

【讨论】:

这行得通。有趣的是我的代码很相似但它不起作用 - 神奇:-)

以上是关于EF手动/动态表注册的主要内容,如果未能解决你的问题,请参考以下文章

asp.net core, Ef core : 在运行时动态映射存储库和服务

将多个表动态映射到单个实体

如何使用 VBA 动态自动填充目标?

SQLDelight:如何动态创建表?

实体框架手动删除的表不能从EF迁移生成

带有 BigQuery 的动态表后缀不限制处理的数据