微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

EF 手动/动态表注册

如何解决EF 手动/动态表注册

我正在尝试手动创建一些表并动态映射到 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<T> 以便应用程序可以在这个集合上调用 Linq。这个方法使用反射来获取DbSet,不过我也试过直接调用Set<T>(typeof(T).Name)

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

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

dotnet ef migrations add InitialCreate

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

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

解决方法

一旦您在 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);
    }
}

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。