【问题标题】:Adding new DbSet to DbContext when application has started and DbContext created当应用程序启动并创建 DbContext 时,将新的 DbSet 添加到 DbContext
【发布时间】:2020-02-10 16:19:06
【问题描述】:

我有一个项目,在业务中它将动态创建表,它与 netcore3.0 和 EF 一起使用。 在动态表创建后创建dbcontext实例时,我会使用Assembly Emit创建一个新类型的表,并使用OnModelCreating方法添加表对应的dbset。

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }

    public virtual DbSet<Book> Books { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        //Use assmbly emit to create dynamic types
        var types = CreateDynamicTypes();

        foreach (var type in types)
        {
            builder.Entity(type);
        }

        base.OnModelCreating(builder);
    }
}

但是在创建dbcontext后创建表时,我还不知道如何添加新的dbset,因为OnModelCreating只运行1次。

问题:如何在创建 dbcontext 实例后添加新的 dbset?

【问题讨论】:

    标签: c# entity-framework dynamic


    【解决方案1】:

    由于性能开销,OnModelCreating 仅运行 1 次(首次初始化时)。

    有一种方法可以绕过这个,使用“模型定制器”

    首先,您需要在 OnConfiguring 中进行一些调整(您需要覆盖基本实现)

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            base.OnConfiguring(optionsBuilder);
    
            var serviceCollection = new ServiceCollection()
                .AddEntityFrameworkSqlServer();
    
    
            serviceCollection = serviceCollection.AddSingleton<IModelCustomizer, YourModelCustomizer>();
    
            var serviceProvider = serviceCollection.BuildServiceProvider();
    
            optionsBuilder
                .UseInternalServiceProvider(serviceProvider);
        }
    

    你的定制器应该看起来像

    public class YourModelCustomizer : ModelCustomizer
        {
            public override void Customize(ModelBuilder modelBuilder, DbContext dbContext)
            {
                base.Customize(modelBuilder, dbContext);
    
                var entityTypeBuilderCart = modelBuilder.Entity<Models.Cart>()
                    .ToTable("ABC");
                entityTypeBuilderCart.Property(a => a.UserId).HasColumnName("XYZ");
                entityTypeBuilderCart.Property(a => a.ContractorId).HasColumnName("DFG");
                entityTypeBuilderCart.Ignore(a => a.CompanyId);
    
                var entityTypeBuilderCartArticle = modelBuilder.Entity<Models.CartArticle>()
                    .ToTable("IJK");
                entityTypeBuilderCartArticle.Property(a => a.UserId).HasColumnName("QWE");
            }
    
            public YourModelCustomizer(ModelCustomizerDependencies dependencies) : base(dependencies)
            {
            }
        }
    

    希望对你有帮助。

    请注意,这种配置可能会导致性能问题。 此代码在 EF Core 2.x 中有效,在 EF 3.x 中可能会有一些变化,而此代码可能需要一些变化。

    【讨论】:

    • 感谢您的快速回复。我试试看
    • 如果 Customize(ModelBuilder, DbContext) 调用每个请求,性能如何?
    • 我可以在有时间的时候尝试做一些基准测试。在您的应用程序中将使用 ModelCustomizer 的 DbContext 和另一个不使用它的 DbContext 分开可能会更好,因为当调用 ModelCustomizer 时,EF 无法充分利用缓存,并且不建议将这种方法用于应用程序,最好重新考虑您的应用程序和使用程序,而不是每次都更改模型。仅调用一次 OnModelCreating 是创建此框架的人员的“设计”目标。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-07
    • 2020-10-19
    • 1970-01-01
    • 2017-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多