27

我正在尝试使实体框架迁移正常工作。我启用了代码优先迁移,它创建了一个迁移文件夹、配置文件和 mig 历史表,但没有初始创建。我错过了一步吗?这是由 EF (4.3.1) 创建的新数据库。

4

6 回答 6

23

默认情况下,此行为不存在,但您可以很容易地以多种不同的形式使用它。

  1. 您可以context.Database.CreateIfNotExists();在应用程序启动时调用。

  2. 您可以使用内置DatabaseInitializers 之一。初始化程序内置在CreateDatabaseIfNotExistsEntityFramework 中,只需将其添加到您的项目中即可。

  3. 您可以创建自己的自定义数据库初始化程序,其中包括选项#1 本身。示例:代码优先迁移和初始化

您可以通过代码或配置文件在项目中包含 DatabaseInitializers。

通过代码包含一个 EntityFramework Database Initializer:

在您的应用程序启动中,您可以像这样设置 DatabaseInitializer:

System.Data.Entity.Database.SetInitializer<DairyMmmContext>(new System.Data.Entity.CreateDatabaseIfNotExists<DairyMmmContext>());

注意:此代码在实体框架的整个生命周期中已多次更改!此示例适用于 EF 4.3,这是可通过 nuget 获得的当前生产版本。

通过配置元素包含一个 EntityFramework Database Initializer:

<configuration>
  <entityFramework>
    <contexts>
      <context type="MyNamespace.MyEFDataContext, AssemblyName">
        <databaseInitializer
          type="System.Data.Entity.CreateDatabaseIfNotExists`2[[MyNamespace.MyEFDataContext, AssemblyName],
               [MyNamespace.Migrations.Configuration,  AssemblyName]], EntityFramework" />
      </context>
    </contexts>
  </entityFramework>
</configuration>

您会注意到这种配置可能有点“不优雅”。您需要将AssemblyName上面替换为您保存实体框架内容的程序集的名称,替换MyNamespace.MyEFDataContext为您的实体框架数据上下文MyNamespace.Migrations.Configuration的完全限定名称,并替换为您的配置类的完全限定名称(默认情况下在您的 Migration 文件夹中项目)。

编辑:编辑以回应其他评论

迁移是从一个模式定义到另一个模式定义的更改。创建空数据库不是迁移(但之后的一切都是)。您的项目中将没有迁移源文件,仅用于创建一个空数据库,这是由初始化程序在代码中完成的。

如果您已经在使用DropCreateDatabaseAlways初始化程序,它应该这样做。但是,我注意到您正在代码中设置初始化程序,这意味着可能会出现计时问题(在您的上下文已经超过调用任何初始化程序的点之后设置初始化程序)。

您可以强制实体框架在代码中的任何位置运行您的初始化程序context.Database.Initialize(true);(参数为真/假以强制初始化,而不管当前状态如何)。每次都会删除并重新创建您的数据库。

但是您也可以确保在应用程序的生命周期中尽早设置您的初始化程序(在您创建上下文的单个实例之前)。

于 2012-08-24T15:26:12.030 回答
19

“初始创建”不是自动创建的!您需要自己创建它。EF的一些教程令人困惑,我和你有同样的误解。

你需要做什么:

-Add-Migration InitialModel

如果您已经创建了数据库表和域模型,那么:

-Add-Migration InitialModel -IgnoreChanges

从这一点开始,您的代码将与数据库同步。每次更改代码时,都可以使用 Add-Migration 将更改添加到数据库中。

于 2013-11-11T05:11:42.473 回答
10

此处(在 microsoft.com 上)的文章/教程 描述了 initialCreate 迁移不存在的原因。仅当数据库已存在时才会添加迁移。否则,第一个迁移将是“initialCreate”,因为创建迁移到尚不存在的数据库是没有意义的……没有数据库意味着在向下迁移时没有任何东西可以回滚。

这是相关的段落:

在 Package Manager Console 中运行 Enable-Migrations 命令此命令已将 Migrations 文件夹添加到我们的项目中,这个新文件夹包含两个文件:

配置类。此类允许您配置迁移在您的上下文中的行为方式。对于本演练,我们将仅使用默认配置。 由于您的项目中只有一个 Code First 上下文,因此 Enable-Migrations 已自动填写此配置适用的上下文类型。

InitialCreate 迁移。之所以生成此迁移,是因为在启用迁移之前,我们已经让 Code First 为我们创建了一个数据库。此脚手架迁移中的代码表示已在数据库中创建的对象。在我们的例子中,它是带有 BlogId 和 Name 列的 Blog 表。文件名包含一个时间戳以帮助排序。

如果尚未创建数据库,则不会将此 InitialCreate 迁移添加到项目中。相反,我们第一次调用 Add-Migration 时,创建这些表的代码将被搭建到新的迁移中。

于 2012-12-20T02:41:09.593 回答
5

不确定它是否相同,但我遇到了类似的问题。我认为我的问题与我不使用配置文件中的连接字符串来获取我的连接字符串这一事实有关。

摆弄解决方案中的启动项目以及包管理器控制台中的项目组合,我能够生成第一个迁移。

还要确保你有一个带有 dbContext 类名称的连接字符串,以便包管理器可以找到它。

于 2012-08-30T23:36:51.977 回答
2

我正在使用 EF 6 RC1 并遇到了这个问题,即在运行 Enable-Migrations 时既没有创建 InitialCreate 也没有创​​建 __MigrationHistory。

实际上,就在从 EF 5 升级到 EF 6 之后,我运行了 Enable-Migrations,由于某种原因,它使用 EF 5 架构创建了一个 __MigrationHistory 表,所以我删除了它和我的 Migrations 目录并尝试重新开始。

但是每次我删除 Migrations 目录时,它都不会创建 InitialCreate 或 __MigrationHistory。我尝试删除并重新创建数据库并重新启动 Visual Studio 2012 无济于事。我放弃了这一天,第二天早上又试了一次——让我的电脑坐了大约 8 个小时后,它创建了 InitialCreate。我猜一定有一个缓存有一个很长的超时时间 - 有人吗?我也猜测重新启动可能会清除缓存,但我没有尝试过。

无论如何,都可以使用PM> Add-Migration InitialCreate手动执行该步骤。

无论如何,我仍然没有得到 __MigrationHistory 表。显然,EF 6 已从在 Enable-Migrations 命令期间创建它改为仅在 Update-Database 命令期间创建它。由于那时我的模式已经创建,我需要将其拆除并手动重新创建它:

PM> Update-Database -TargetMigration:0
PM> Update-Database

我还在第一个命令后停止检查数据库的状态,以确保我正在更新正确的,因为根据这个,数据库连接字符串会根据配置被拾取或自动生成,除非配置正确,否则会有不能保证您将访问您打算访问的数据库或 SQL Server 实例。

在运行这两个命令后,它创建了一个 __MigrationHistory 表 - 它并没有将它创建为系统表(无论如何我并不真正想要),所以一切都很好。与 OP 的问题不完全相同,但希望这对其他人有帮助。

参考:

于 2013-10-08T12:05:38.200 回答
1

我知道这很旧,但没有公认的答案,我也有同样的问题。

诀窍是 Enable-Migrations 命令。如此处所述有一个命令Enable-Migrations –EnableAutomaticMigrations。它的作用是在您所在的位置开始迁移。

如果您希望第一次迁移是创建数据库,只需运行Enable-Migrations(不带 --EnableAutomaticMigrations)。

并记住设置初始化程序:

            Database.SetInitializer(new MigrateDatabaseToLatestVersion<LicenseContext, Configuration>());
于 2017-07-27T12:12:08.270 回答