如何为多个上下文启用EF迁移以分别连接不同的数据库?

132

我该如何在同一个项目中为多个数据库上下文启用Entity Framework 5(版本5.0.0)迁移?每个上下文对应一个自己的数据库。当我在PM控制台(Visual Studio 2012)中运行Enable-Migrations时,由于存在多个上下文而导致错误:

PM> Enable-Migrations
More than one context type was found in the assembly 'DatabaseService'.
To enable migrations for DatabaseService.Models.Product1DbContext, use Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContext.
To enable migrations for DatabaseService.Models.Product2DbContext, use Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContext.

如果我运行Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContext,那么我将不被允许运行Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContext,因为已经存在一个迁移: 在项目 'DatabaseService' 中已启用迁移。要覆盖现有的迁移配置,请使用 -Force 参数。


4
请参阅 Julie Lerman 的文章 Data Points - EF6 Code First Migrations for Multiple Models,该文章介绍了如何使用 Entity Framework 6 中的 Code First 迁移来处理多个模型。 - Developer Marius Žilėnas
8个回答

134

第二次调用 Enable-Migrations 失败,因为 Configuration.cs 文件已经存在。如果您重命名该类和文件,应该能够运行第二个 Enable-Migrations,它将创建另一个 Configuration.cs。

然后,您需要指定在更新数据库时要使用哪个配置。

Update-Database -ConfigurationTypeName MyRenamedConfiguration

1
什么是"MyRenamedConfiguration"? - Robert Noack
1
"MyRenamedConfiguration" 只是一个示例占位符文本。您可以将原始的 Configuration.cs 重命名为任何名称(例如 FooBar),然后运行 Update-Database -ConfigurationTypeName FooBar。 - ckal
4
更新数据库命令:Update-Database -conf MyRenamedConfiguration(缩写形式)。 - Peter Kerr
我还必须将MigrationHistory中的ContextKey更改为新的命名空间。这是一个不错的链接。https://dev59.com/KmYq5IYBdhLWcg3w8lJo#48809668 - cytek04

106

除了@ckal提出的建议外,关键是给每个重命名的Configuration.cs文件指定自己的命名空间。如果不这样做,EF会尝试将迁移应用于错误的上下文。

以下是我使用的具体步骤。

如果迁移出现问题并且您想创建新的“基线”:

  1. 删除Migrations文件夹中的任何现有.cs文件
  2. 在SSMS中,删除__MigrationHistory系统表。

创建初始迁移:

  1. 在软件包管理器控制台中:

  2. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
    
    在解决方案资源管理器中:将Migrations.Configuration.cs重命名为Migrations.ConfigurationA.cs。如果使用Visual Studio,则应自动重命名构造函数。确保它已经被重命名。 编辑ConfigurationA.cs:将命名空间更改为NamespaceOfContext.Migrations.MigrationsA。
    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
    
    在解决方案资源管理器中:将Migrations.Configuration.cs重命名为Migrations.ConfigurationB.cs。再次确保构造函数的名称也相应更改。 编辑ConfigurationB.cs:将命名空间更改为NamespaceOfContext.Migrations.MigrationsB。
    add-migration InitialBSchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB 
    
  3. Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
    
  4. add-migration InitialSurveySchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationA -ProjectName ProjectContextIsInIfNotMainOne -StartupProjectName
    NameOfMainProject  -ConnectionStringName ContextA 
    
  5. Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA
    
    在程序包管理器控制台中创建迁移脚本的步骤:
    1. 运行以下命令:

    2. Add-Migration MYMIGRATION -ConfigurationTypeName ConfigurationA -ProjectName
      ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
      -ConnectionStringName ContextA
      
      或 -
      Add-Migration MYMIGRATION -ConfigurationTypeName ConfigurationB -ProjectName
      ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
      -ConnectionStringName ContextB
      

      可以反复运行此命令,直到更改应用于数据库为止。

    3. 要么对所需的本地数据库运行脚本,要么在本地应用Update-Database而不使用 -Script:

    4. Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
      ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
      -ConnectionStringName ContextA
      
      或 -
      Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
      ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
      -ConnectionStringName ContextB
      

#4 更改:编辑 ConfigurationA.cs -> 编辑 ConfigurationB.cs - Brian Rizo
1
@Biran:感谢您注意到这一点。我已经编辑了答案。请注意,您也可以自己编辑答案。由于您还没有2000个声望值,您的答案将进入审核队列,但该队列通常会快速处理,因此您的编辑很可能会在几分钟内获得批准。 - Eric J.
5
谢谢!那就是我所缺少的(命名空间)。 - William M. Rawls
3
这对我很有帮助!完整的说明包含所有选项和顺序。省去了我数小时的时间。 - elcool
1
您,先生,已经在多个项目中为我节省了无数个小时的痛苦。非常感谢您。 - caliche2000
显示剩余8条评论

88

我刚遇到了同样的问题,我使用了以下解决方案(全部来自包管理器控制台)

PM> Enable-Migrations -MigrationsDirectory "Migrations\ContextA" -ContextTypeName MyProject.Models.ContextA
PM> Enable-Migrations -MigrationsDirectory "Migrations\ContextB" -ContextTypeName MyProject.Models.ContextB

这将在“迁移”文件夹中创建2个单独的文件夹,每个文件夹将包含生成的Configuration.cs文件。不幸的是,您仍然需要重命名这些Configuration.cs文件,否则会出现两个文件的问题。我将我的文件重命名为ConfigA.csConfigB.cs

编辑:(由Kevin McPheat提供)请记住,在重命名 Configuration.cs 文件时,也要重命名类名称和构造函数。/编辑

采用这种结构,您只需执行

PM> Add-Migration -ConfigurationTypeName ConfigA
PM> Add-Migration -ConfigurationTypeName ConfigB

这将在与配置文件相邻的文件夹内创建迁移的代码文件(这样做可以将这些文件保持在一起,非常不错)。

PM> Update-Database -ConfigurationTypeName ConfigA
PM> Update-Database -ConfigurationTypeName ConfigB

最后但同样重要的是,这两个命令将会把正确的迁移应用到它们对应的数据库。

编辑于2016年2月8日: 我已经试过 EF7 版本 7.0.0-rc1-16348

我无法让 -o|--outputDir 选项起作用。它一直在给出 Microsoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument 的错误信息。

然而,看起来第一次添加迁移时,它会被添加到 Migrations 文件夹中,之后为另一个上下文添加的迁移会自动放置在 Migrations 子文件夹中。

原始名称 ContextA 看起来违反了某些命名规范,所以我现在使用 ContextAContextContextBContext。使用这些名称,您可以使用以下命令: (注意我的 dnx 仍然可以从包管理器控制台工作,我不想打开单独的 CMD 窗口进行迁移)

PM> dnx ef migrations add Initial -c "ContextAContext"
PM> dnx ef migrations add Initial -c "ContextBContext"

这将在 Migrations 文件夹中为 ContextAContext 创建一个模型快照和初始迁移。它将为 ContextBContext 创建一个名为 ContextB 的文件夹,其中包含这些文件。

我手动添加了一个 ContextA 文件夹,并将迁移文件从 ContextAContext 移动到该文件夹中。然后我重命名了这些文件中的命名空间(快照文件、初始迁移以及注意初始迁移文件下还有第三个文件……designer.cs)。我需要向命名空间中添加 .ContextA,然后框架再次自动处理它。

使用以下命令会为每个上下文创建一个新迁移:

PM>  dnx ef migrations add Update1 -c "ContextAContext"
PM>  dnx ef migrations add Update1 -c "ContextBContext"

生成的文件会被放置在正确的文件夹中。


5
最佳解决方案,简单易行,并且我们会保持一个清晰的文件夹。 - Malick
2
这就是我需要的答案。通过 -MigrationsDirectory 添加的命名空间就是答案!谢谢。 - Crob
1
好的,干净利落的解决方案。谢谢。 - Stefan Cebulak
4
一年半后,我很高兴能够使用自己的帖子来建立一个新项目。 - bart s
1
注意,当您运行add-migration时,它会提示您输入Name。这让我有点困惑,因为我已经提供了ConfigurationTypeName,当它只显示Name:时,我有一点恼怒。但是,它所需要的名称是“可读性强”的更改描述 - 例如:'AddedProducts'或'IncreaseLengthOfNameFields'。在迁移文件夹中,您可以将其作为类名的一部分获得,因此很容易看出其中的内容。因此,在效果上,“名称”有点像一个签入注释。 - Simon_Weaver

8

假设您已经有一个包含许多迁移的“配置”,并且希望保持原样,您可以随时创建一个新的“配置”类,并赋予它另一个名称,例如

class MyNewContextConfiguration : DbMigrationsConfiguration<MyNewDbContext>
{
   ...
}

然后只需输入命令。
Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

EF会无问题地生成迁移脚本。最后,更新你的数据库,从现在开始,如果你不告诉EF要更新哪个配置,它会抱怨。

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

完成。

您无需处理 Enable-Migrations,因为它会抱怨“Configuration”已经存在,并且重命名现有的 Configuration 类将给迁移历史记录带来问题。

您可以针对不同的数据库或相同的数据库,所有配置将很好地共享 __MigrationHistory 表。


6
如果有更多的数据库存在,请使用以下的PowerShell代码。
Add-Migration Starter -context EnrollmentAppContext 
  • 'Starter'是迁移名称

  • 'EnrollmentAppContext'是我的应用程序上下文的名称

您可以通过以下方式在VS中打开PowerShell: 工具->NuGet程序包管理器->包管理器控制台


5

要在 PowerShell 中更新数据库,请执行以下代码...

Update-Database -context EnrollmentAppContext

*如果存在多个数据库,才使用此代码,否则不需要..


0

针对EF Core中的多个DbContext; 最简单的方法,至少对于我这样的新手:

  1. 创建2个不同的DbContext,您可以使用相同的数据库,但使用2个不同的连接字符串。
  2. 使用@Ahamed AAQIB的答案运行每个迁移: "add-migration MigrationName -context EnrollmentAppContext" "Update-Database -context EnrollmentAppContext"

这并没有回答问题。一旦您拥有足够的声望,您将能够评论任何帖子;相反,提供不需要询问者澄清的答案。- 来自审核 - Arani

0

EF 4.7 在运行 Enable-migrations 命令时,实际上会提示你存在多个上下文。

在程序集 'Service.Domain' 中发现了多个上下文类型。

To enable migrations for 'Service.Domain.DatabaseContext.Context1', 
use Enable-Migrations -ContextTypeName Service.Domain.DatabaseContext.Context1.
To enable migrations for 'Service.Domain.DatabaseContext.Context2',
use Enable-Migrations -ContextTypeName Service.Domain.DatabaseContext.Context2.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接