如何使用实体框架代码优先使用较新的数据库模型版本

时间:2015-08-28 07:35:24

标签: c# entity-framework

也许是一个奇怪的问题,但我们有一个场景,我们希望在一个环境中使用Entity Framework代码优先,该环境可能有一个比代码本身更新/更高版本的数据库。

让我详细说明一下。我们有几个解决方案都使用核心组件,其中包含所有解决方案都使用的整体数据模型。解决方案主要是部署到多个不同Azure网站的站点和应用程序。所以解决方案彼此相邻。他们共享的唯一内容是Azure数据库。

现在情景将会发挥作用。当我们更新核心程序集中的数据库模型并更新Azure中的一个解决方案时。在该解决方案中加载模型时,将更新基础数据库。没问题,就像魅力......

当加载其他解决方案之一时,问题就开始了。这些其他解决方案仍然使用以前的核心组件,与他们连接的数据库模型相比,现在已经过时的EF CF模型。所以抛出一个很好的例外,如下所示。

  

自创建数据库以来,支持“{NAME}”上下文的模型已更改。手动删除/更新数据库,或使用IDatabaseInitializer实例调用Database.SetInitializer。例如,DropCreateDatabaseIfModelChanges策略将自动删除并重新创建数据库,并可选择使用新数据对其进行播种。

问题是我们是否可以强制模型加载并忽略数据库中所做的更改。我们内部有一个策略,只在数据库中应用不破坏更改,因此模型应该能够正常加载。

提前感谢您提供的信息和提示!

2 个答案:

答案 0 :(得分:2)

我可能错了(不确定我是否记得正确),但如果它不干扰您的应用程序配置,您可以将DB初始化程序设置为null:

    public PortalDbContext()
        : base("name=PortalConnectionString")
    {
        Database.SetInitializer<PortalDbContext>(null);
    }

或者可以创建自定义初始化程序:

public class BlogContextCustomInitializer : IDatabaseInitializer<BlogContext>
{
    public void InitializeDatabase(BlogContext context)
    {
        if (context.Database.Exists())
        {
            if (!context.Database.CompatibleWithModel(true))
            {
                // Do something...
            }
        }
    }
}

答案 1 :(得分:1)

如果您使用的是EF Code-First,则模型必须与数据库匹配。

即使你找到了绕过这种限制的方法,你也会做一些危险的事情。

让我对它进行评估:如果您从“解决方案A”更新数据库,“A”中的模型将与数据库匹配,并且此解决方案中对模型的任何进一步更改都可以应用于数据库而不会出现任何问题所有。那就对了!。但是,如果你在这个问题中做了什么,即你做了一些事情,以便“解决方案B”能够继续工作,即使模型没有数学与数学,然后你在“解决方案B“,你如何应用它? “解决方案B”如何知道应用哪些更改? “B”如何确定“A”所做的更改应该保留原样,“B”必须应用于数据库的新更改是什么?

如果您可以按照这样的方式继续操作,那么您将完成两个不同代码的第一个模型,其中没有一个与数据库匹配,此外,您如何保证两个应用程序都能正常工作?如何确保“A”上的更改不会影响“B”上的代码,反之亦然?

避免此问题的最安全的解决方案是在两个解决方案之间共享包含代码优先模型的程序集。任何其他解决方案迟早会很麻烦。也许你必须重构你的解决方案,以便他们可以共享相同的DbContext。 DbContext必须是项目中唯一的东西。我通常有一个实体项目,以及一个引用实体的DbContext项目。然后两个解决方案都会引用这些项目。这些项目可以在其中一个解决方案中,也可以在完全不同的解决方案中。当然,在一个或两个解决方案中,您必须添加对DbContext程序集的引用,而不是项目,并保持更新,您可以使用后构建脚本。这样,当您重新编译解决方案时,您还会检测到对一个解决方案所做的不兼容更改,这会对另一个解决方案产生负面影响。

EF6在同一个数据库中支持多个不同的DbContext,因此,如果您的每个应用程序都有不同的,非冲突的DbContext,那么您就不会遇到问题。我无法检查它是否正确,但我认为每个解决方案中DbContext的名称必须不同(我不记得是否考虑了名称空间)。通过非冲突,我的意思是它们引用不同的数据库对象(表,视图或其中任何一个),两个上下文引用的对象都不会更改(例如主表)。