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

本文关键字:实体 框架 代码 版本 数据库模型 | 更新日期: 2023-09-27 18:10:07

也许是一个奇怪的问题,但是我们有一个场景,我们想要在一个环境中使用实体框架代码,这个环境可能有一个比代码本身更新/更高版本的数据库。

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

现在这个场景将发挥作用。当我们更新核心程序集中的数据库模型和更新Azure中的一个解决方案时。当模型被加载到该解决方案中时,底层数据库将被更新。没问题,很有魅力。

当加载其他解决方案之一时,问题就开始了。这些其他解决方案仍然使用以前的核心程序集,与它们连接的数据库模型相比,现在的EF CF模型已经过时了。因此,将抛出一个漂亮的异常,如下所示。

支持'{NAME}'上下文的模型自数据库创建以来已经更改。要么手动删除/更新数据库,要么调用database。使用IDatabaseInitializer实例设置初始化器。例如,DropCreateDatabaseIfModelChanges策略将自动删除和重新创建数据库,并可选择使用新数据播种。

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

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

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

我可能是错的(不确定我是否记得正确),但如果它不干扰您的应用程序配置,您可以将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...
            }
        }
    }
}

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

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

让我解释一下:如果您从"解决方案A"更新数据库,"A"中的模型将与数据库匹配,并且对该解决方案中模型的任何进一步更改都可以应用到数据库中,而不会出现任何问题。这是正确的!然而,如果你做你在这个问题上问什么,即你做一些事情,使"解决方案B"可以继续工作,即使模型不与数据库数学,然后你改变了模型在"解决方案B",你如何应用它?"解决方案B"如何知道要应用哪些更改?"B"如何确定"A"所做的哪些更改应该保持原样,以及"B"所做的哪些新更改必须应用于数据库?

如果您能像这样继续下去,那么您将完成两个不同的代码优先模型,其中没有一个与数据库匹配,而且,您如何保证两个应用程序都能正确工作呢?如何确保"A"上的更改不会影响"B"上的代码,反之亦然?

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

EF6在同一数据库中支持多个不同的DbContext,因此,如果每个应用程序都有不同的、不冲突的DbContext,则不会有问题。我不能正确地检查它,但我认为DbContext的名称在每个解决方案中一定是不同的(我不记得是否考虑了名称空间)。所谓不冲突,我的意思是它们引用不同的数据库对象(表、视图或其他),其中两个上下文引用的对象不会改变(例如主表)。