【问题标题】:Does an equivalent to Database.CompatibleWithModel(bool) exist in EF CoreEF Core 中是否存在等效于 Database.CompatibleWithModel(bool)
【发布时间】:2018-03-14 03:01:05
【问题描述】:

我正在开发一个使用 EFCore 2.1.0-preview1-final 代码优先方法的项目。就像在 EF6(和以前的版本)中一样,我想确保我的 DbContext(和模型)与数据库的兼容性。

在 EF6 中默认启用它,并且可以使用 Database.CompatibleWithModel(false); 将其停用。据我所知,EF 使用存储模型信息的__MigrationHistory 表。 EFCore 在__EFMigrationsHistory 表中没有可以提供此类信息的列。

我在 EFCore 中找不到任何有关兼容性检查的信息。但我想确保兼容性,因为经过一些测试,它似乎默认没有启用(或确实存在)。我通过手动添加和删除数据库中的一些列并在修改后执行应用程序来测试它。我 - 出乎我的意料 - 没有收到任何异常。

有人知道如何实现从模型到数据库的兼容性检查,反之亦然,就像在 EF6 中的 EFCore 一样? 或者可以提供一些有用的链接以获取有关它的更多信息或为什么它在 EFCore 中不存在(因为它不是必需的)?

【问题讨论】:

  • EF6 没有做那么多。它只是确保自上次 EF 更改数据库架构以来模型没有更改。它不会检测在 EF 之外进行的架构更改。
  • 嗯,好的。我不知道如何使用 EF Core 做同样的事情。也许我必须检查 EF 中的实现。

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


【解决方案1】:

强烈建议不要这样做,因为它使用内部组件并且容易出错,但这是一种方法。

using (var db = new MyDbContext())
{
    var reporter = new OperationReporter(handler: null);
    var designTimeServiceCollection = new ServiceCollection()
        .AddSingleton<IOperationReporter>(reporter)
        .AddScaffolding(reporter);
    new SqlServerDesignTimeServices().ConfigureDesignTimeServices(designTimeServiceCollection);

    var designTimeServices = designTimeServiceCollection.BuildServiceProvider();

    var databaseModelFactory = designTimeServices.GetService<IScaffoldingModelFactory>();
    var databaseModel = (Model)databaseModelFactory.Create(
        db.Database.GetDbConnection().ConnectionString,
        tables: new string[0],
        schemas: new string[0],
        useDatabaseNames: false);

    var currentModel = db.Model;

    // Fix up the database model. It was never intended to be used like this. ;-)
    foreach (var entityType in databaseModel.GetEntityTypes())
    {
        if (entityType.Relational().Schema == databaseModel.Relational().DefaultSchema)
        {
            entityType.Relational().Schema = null;
        }
    }
    databaseModel.Relational().DefaultSchema = null;
    databaseModel.SqlServer().ValueGenerationStrategy =
        currentModel.SqlServer().ValueGenerationStrategy;
    // TODO: ...more fix up as needed

    var differ = db.GetService<IMigrationsModelDiffer>();

    if (differ.HasDifferences(databaseModel, currentModel))
    {
        throw new Exception("The database and model are out-of-sync!");
    }
}

【讨论】:

  • 非常感谢。好吧,我不会使用它,因为你反对它。我只是想知道这怎么可能。您是否有一些链接可以让我了解 EFCore 不支持此功能的原因?
  • 没有文档。我们看到两个开发选项:1)您的域模型是事实的来源,您使用迁移来管理数据库模式。 2)您的数据库模式是事实的来源,您使用数据库(#831)的逆向工程/更新模型来保持您的域模型同步。没有单一的事实来源会变得太混乱,需要像 CompatibleWithModel 这样的工具来帮助保持一切同步。 This answer 描述了您可以执行的其他同步检查。
  • 好的,我完全同意你的看法。仅备注如下场景:另一个开发人员或管理员删除了数据库中的整数列。此时数据库仅用于读取数据 - 不插入新数据。由于架构修改,您不会收到异常。因此,您始终拥有默认的 int 值 0。如果我使用 EF6,兼容性检查将在创建第一个 DbContext 对象时引发异常。 (每个原始数据类型的行为相同)过去我已经遇到过这样的问题。谢谢。 :)
  • 我问了一个更新的问题here。在 v5 中是否有一种“安全”的方法可以做到这一点,而不依赖于组件内部?
猜你喜欢
  • 2020-06-12
  • 2017-06-26
  • 2019-03-02
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2011-10-04
  • 2020-04-13
  • 1970-01-01
相关资源
最近更新 更多