实体框架代码首先确定数据库是否兼容

时间:2018-03-12 08:02:17

标签: c# entity-framework-6 ef-code-first

我们的项目包含两个使用相同模型访问同一数据库的应用程序。 两个应用程序都使用相同的引导机制,如果数据库与模型不兼容,它将删除数据库并重新创建它。它使用以下代码:

    private bool DropCreateDatabaseIfModelChanged(TContext context)
    {
        if (context.Database.Exists())
        {
            if (context.Database.CompatibleWithModel(throwIfNoMetadata: true))
            {
                return false;
            }

            context.Database.Delete();
        }

        var createDatabaseCollationInterceptor = new CreateDatabaseCollationInterceptor(Constants.Database.COLLATION);
        DbInterception.Add(createDatabaseCollationInterceptor);
        context.Database.Create();
        DbInterception.Remove(createDatabaseCollationInterceptor);

        return true;
    }

第二个应用程序仅使用第一个模型的子集,当调用上面的函数context.Database.CompatibleWithModel(throwIfNoMetadata: true)时返回false并且数据库被删除。

如果符合以下情况,

CompatibleWithModel将返回true:

For Code First the model is considered compatible if the model is stored in the database in the Migrations history table and that model has no differences from the current model as determined by Migrations model differ

问题:如果模型只包含整个模型的子集,我怎样才能确定模型是否兼容(我知道它是什么)?

[编辑]关于架构的一些话

  • 应用程序1公开RESTful API(由前端使用)
  • 应用程序2暴露SOAP端点(为此创建第二个应用程序的原因是不混合堆栈)
  • 应用程序1由5个模块组成(模块是跨越从数据访问到UI的完整堆栈的逻辑功能)
  • 应用程序2引用了应用程序1的2个模块(只有它需要的模块)
  • 模块没有引用其他模块中的实体
  • 正在使用公共数据库上下文来初始化数据库,同时保持权限定义彼此分离。对于除公共基本模块
  • 之外的所有模块都是如此

[Edit2]添加了描述使用SharedTables的应用程序交互的工作流程 enter image description here

1 个答案:

答案 0 :(得分:0)

首先使用代码时,最简单的方法是在同一个数据库中启用多个模型共同使用separate migration history tables

TL;来自链接文章的DR:对于每个单独的模型,创建一个像这样的新类

using System.Data.Common;
using System.Data.Entity;
using System.Data.Entity.Migrations.History;

namespace CustomizableMigrationsHistoryTableSample
{
    public class MyHistoryContext : HistoryContext
    {
        public MyHistoryContext(DbConnection dbConnection, string defaultSchema)
            : base(dbConnection, defaultSchema)
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            // "MigrationHistory" would have to be renamed for each subset model
            modelBuilder.Entity<HistoryRow>().ToTable(tableName: "MigrationHistory", schemaName: "admin");
            modelBuilder.Entity<HistoryRow>().Property(p => p.MigrationId).HasColumnName("Migration_ID");
        }
    }
}

并将其添加到您的设置中:

using System.Data.Entity;

namespace CustomizableMigrationsHistoryTableSample
{
    public class ModelConfiguration : DbConfiguration
    {
        public ModelConfiguration()
        {
            this.SetHistoryContext("System.Data.SqlClient",
                (connection, defaultSchema) => new MyHistoryContext(connection, defaultSchema));
        }
    }
}

我使用这种方法将有限接口(即前端/公共api)的运行时与管理接口(后端api)强烈分开,以限制bug /攻击面。我建议在模型子集上进行某种代码共享,以避免模式漂移。

我从未尝试过这是您的特定情况(完全丢弃不兼容的数据库),因此可能需要进行一些调整。在为现有数据库设置单独的模型(至少是子集模型)时,您需要执行Add-Migration Initial -IgnoreChanges之类的操作,有关详细信息,请参阅this question