实体框架:使用多个自定义历史记录上下文

时间:2016-10-04 09:00:45

标签: c# asp.net-mvc entity-framework

我有将__MigrationHistory映射到现有数据库表的代码。

namespace Alvin_CMS.Migrations
{
    public class CustomHistoryContext : HistoryContext
    {
        public CustomHistoryContext(DbConnection dbConnection, string defaultSchema)
        : base(dbConnection, defaultSchema)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<HistoryRow>().ToTable(tableName: "__MigrationHistory", schemaName: "dbo");
            //modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasColumnName("Migration_ID");
        }
    }

    public class CustomHistoryConfiguration : DbConfiguration
    {
        public CustomHistoryConfiguration()
        {
            this.SetHistoryContext("System.Data.SqlClient",
            (connection, defaultSchema) => new CustomHistoryContext(connection, "dbo"));
        }
    }
}

我还有另一个自定义历史记录上下文:

namespace EAccounting.Migrations
{
    public class CustomHistoryContext : HistoryContext
    {
        public CustomHistoryContext(DbConnection dbConnection, string defaultSchema)
            : base(dbConnection, defaultSchema)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<HistoryRow>().ToTable(tableName: "__MigrationHistory", schemaName: "EAccounting");
            //modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasColumnName("Migration_ID");
        }
    }

    public class CustomHistoryConfiguration : DbConfiguration
    {
        public CustomHistoryConfiguration()
        {
            this.SetHistoryContext("System.Data.SqlClient",
            (connection, defaultSchema) => new CustomHistoryContext(connection, "EAccounting"));
        }
    }
}

我在我的代码中称之为:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<EAccounting.Models.EAccountingMigrationDBContext, EAccounting.Migrations.Configuration>()); 

我有多个数据库,它们都有自己的自定义迁移历史记录上下文。如何让迁移历史记录的数据库初始化程序选择它们将使用哪个历史记录上下文?

3 个答案:

答案 0 :(得分:1)

我有一个系统,在两个不同的程序集中有两个不同的DbContext子类,这两个上下文使用两个不同的HistoryContexts。我的诀窍是使用两个不同的HistoryContext ,并确保每个DbContext子类的DbMigrationsConfiguration子类包含在数据库初始化时注册正确的HistoryContext子类的代码。

基本数据库迁移类:

   public class DbMigrationsConfigurationBase<TContext> : DbMigrationsConfiguration<TContext>, IDbMigrationsConfiguration<TContext> where TContext : DbContext, IDbContext
{
    public DbMigrationsConfigurationBase(Func<DbConnection, string, HistoryContext> historyContextFactory)
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
        MigrationsDirectory = @"Migrations";
        RegisterHistoryContextFactory(historyContextFactory);
    }

    private void RegisterHistoryContextFactory(Func<DbConnection, string, HistoryContext> historyContextFactory)
    {
        foreach (ConnectionStringSettings connectionString in ConfigurationManager.ConnectionStrings)
        {
            if (!string.IsNullOrEmpty(connectionString.ProviderName))
            {
                SetHistoryContextFactory(connectionString.ProviderName, historyContextFactory);
            }
        }
    }

    public IDbMigrator GetMigrator()
    {
        return new DbMigratorWrapper(new DbMigrator(this));
    }
}

特定于上下文的迁移配置类示例:

    public sealed class MySpecialDatabaseMigrationConfiguration : DbMigrationsConfigurationBase<MySpecialDatabase>
{
    private static readonly Func<DbConnection, string, HistoryContext> HistoryContextFactory =
        (connection, schema) => new MySpecialDatabaseHistoryContext(connection, schema);
    public MySpecialDatabaseMigrationConfiguration(): base(HistoryContextFactory)
    {
        ContextKey = "MyNamespace.MySpecialDatabase";
    }
}

然后在我的数据库初始化程序中,我确保在初始化时实例化迁移配置...

    public class CreateOrMigrateDatabaseInitializer<TContext, TConfiguration> : IDatabaseInitializer<TContext>
    where TContext : DbContext, IDbContext
    where TConfiguration : IDbMigrationsConfiguration<TContext>, new()
{
    private readonly string _connection;

    public CreateOrMigrateDatabaseInitializer(string connection, ILogger logger = null)
    {
        Contract.Requires(!string.IsNullOrEmpty(connection), "connection");
        _connection = connection;
    }

    public void InitializeDatabase(TContext context)
    {
        Contract.Requires(context != null, "context");

        IDbMigrationsConfiguration<TContext> configuration = new TConfiguration()
        {
            TargetDatabase = new DbConnectionInfo(_connection)
        };

        if (!context.Database.Exists() || !context.Database.CompatibleWithModel(throwIfNoMetadata: false))
        {
            var migrator = configuration.GetMigrator();

            foreach (string s in migrator.GetPendingMigrations())
            {
                migrator.Update(s);
            }
        }

        Seed(context);

        context.SaveChanges();
    }

} 

答案 1 :(得分:0)

我首先使用代码运行6.2.0。 我只为每个DbContext使用不同的模式

在DbContext中我设置了默认架构

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("schema1");
    }

这会为每个DbContext

生成一个单独的__MigrationHistory表

答案 2 :(得分:0)

您必须在上下文上方添加属性,例如:

[DbConfigurationType(typeof(CustomeConfiguration))]

然后尝试在全局asax或应用程序配置中初始化上下文之前注册配置。

DbConfiguration.SetConfiguration(new TDBConfigurations());

参考:https://docs.microsoft.com/en-us/ef/ef6/fundamentals/configuring/code-based