2

我的数据库模型(有时称为“上下文”)在启动时根据安装的服务和/或插件动态组装。插件和服务通过我的 IoC 容器导出它们的模型定义片段,应用程序核心在调用方法时将它们拾取并运行它们DbContext.OnModelCreating

问题是:我可以(以及如何)在此设置中使用 Code First 迁移吗?
(以下是有关我尝试过的方法以及具体问题的更多信息)

在我之前的项目中,数据库是从一些旧代码继承而来的,所以无论如何我们都不能使用任何 Code First 数据库生成的东西。我们只是保留了一长串 delta 脚本并在部署时手动执行它们(这是一种单主机项目)。

现在我开始了一个新项目,这一次,数据库是全新的,可以使用 Code First。最初,我对 Code First 迁移感到非常兴奋,这似乎是要走的路。直到我真正尝试过。很明显,最初的尝试失败了,因为DbContext我的项目中没有明确定义。

到目前为止,似乎唯一可行的选择是手动编码迁移,我对此非常满意。然而,事实证明这并不像仅仅创建几个继承自DbMigration.

在对一个小型测试项目进行了一些实验之后,我发现迁移自动生成器添加了 的实现IMigrationMetadata,其中包含我的模型的哈希值作为SourceTarget属性的值。据推测,此哈希随后用于识别从数据库的“当前”状态(如__MigrationHistory表中记录)到代码中模型定义的最新状态的迁移路径。这完全有道理,但是...

自然,我不知道从哪里获取模型的哈希值,这使我无法IMigrationMetadata在迁移中实现。

另一方面,我看到元数据接口不包含在DbMigration类本身中,这让我认为它可能是可选的。然后,迁移实际上可以在没有哈希值的情况下工作,但问题是 - 如何?

我在互联网上能找到的所有信息都只是简单的、非常基础的教程。没有关于如何手动创建迁移的信息(以及它是否受支持)。没有关于它如何实际工作以及如何扩展它的文档。而且从外面看也不是很明显。
此时我已准备好求助于 ILSpy,但整个 EF 非常复杂,我担心我可能无法在合理的时间内找到我需要的东西。

4

2 回答 2

1

这里有一些想法,您可以将它们结合起来找到适合您的解决方案。我意识到我在我们的另一个线程中提到了其中的一些,但我将它们包括在此处以供其他阅读此问题的人使用。

  • 自动迁移允许 Code First 自动计算并将更改应用到数据库。
  • 您可以编写自己的代码来生成和应用迁移。我写了一篇关于应用迁移的文章, MigrationsScaffolder类将帮助您创建迁移。
于 2012-11-28T19:08:53.133 回答
0

运行项目时,会在数据库中创建一个额外的表。

              EdmMetadata table

哈希始终是在 EdmMetadata 实体和当前代码优先模型的帮助下创建的。它是存储在数据库的 EdmMetadata 表中的 SHA-256 哈希。你可以从那张桌子上得到它。

要遵循的方法将是:

  1. 使用获取当前模型的哈希

              var hash=GetModelHash(OldContext);
    
  2. 检查代码中的模型(新模型)是否与数据库中的模型(旧模型)兼容

               CompatibleWithModel(hash,CurrentContext,ObjectContext)
    

此方法返回bool

  1. 如果不兼容,则删除数据库中现有的表。

  2. 创建新表

  3. 将当前哈希保存到数据库

  4. 播种数据。

代码可能如下所示:

                {
                        var objectContext = ((IObjectContextAdapter)context).ObjectContext;
                        var modelHash = GetModelHash(objectContext);
                        if (CompatibleWithModel(modelHash, context, objectContext))
                            return;
                        DeleteExistingTables(objectContext);
                        CreateTables(objectContext);
                        SaveModelHashToDatabase(context, modelHash, objectContext);
                        SeedData(context);
                }

一定要让类继承自

    IDatabaseInitializer<T> where T:DbContext
于 2012-11-22T19:22:18.820 回答