Как включить EF-миграции для разных контекстов для разделения баз данных?

Как включить миграцию Entity Framework 5 (версия 5.0.0) для нескольких контекстов БД в том же проекте, где каждый контекст соответствует собственной базе данных? Когда я запускаю Enable-Migrations в консоли PM (Visual Studio 2012), появляется ошибка из-за наличия нескольких контекстов:

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, потому что миграция уже существует: Migrations have already been enabled in project 'DatabaseService'. To overwrite the existing migrations configuration, use the -Force parameter.

Ответ 1

Второй вызов Enable-Migrations не работает, потому что файл Configuration.cs уже существует. Если вы переименуете этот класс и файл, вы должны будете запустить эту вторую Enable-Migrations, которая создаст другую Configuration.cs.

Затем вам нужно указать, какую конфигурацию вы хотите использовать при обновлении баз данных.

Update-Database -ConfigurationTypeName MyRenamedConfiguration

Ответ 2

В дополнение к тому, что предложил @ckal, это критический, чтобы дать каждому переименованному Configuration.cs собственное пространство имен. Если вы этого не сделаете, EF попытается применить миграции к неправильному контексту.

Вот конкретные шаги, которые хорошо работают для меня.

Если Миграции перепутаны, и вы хотите создать новую "базовую линию":

  • Удалите все существующие файлы .cs в папке Migrations
  • В SSMS удалите системную таблицу __MigrationHistory.

Создание начальной миграции:

  • В консоли диспетчера пакетов:

    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 
    
  • Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
    
  • add-migration InitialSurveySchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationA -ProjectName ProjectContextIsInIfNotMainOne -StartupProjectName
    NameOfMainProject  -ConnectionStringName ContextA 
    
  • Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA
    

Шаги по созданию сценариев миграции в консоли диспетчера пакетов:

  • Запустить команду

    Add-Migration MYMIGRATION -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA
    

    или -

    Add-Migration MYMIGRATION -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
    

    ОК, чтобы повторно запустить эту команду, пока в базу данных не будут внесены изменения.

  • Либо запускайте скрипты с нужной локальной базой данных, либо запустите Update-Database без - Script, чтобы применить локально:

    Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA
    

    или -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
    

Ответ 3

Я просто столкнулся с той же проблемой, и я использовал следующее решение (все из консоли диспетчера пакетов)

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

Это создаст две отдельные папки в папке Migrations. Каждый из них будет содержать сгенерированный файл Configuration.cs. К сожалению, вам все равно придется переименовывать те файлы Configuration.cs, иначе будут жалобы на наличие двух из них. Я переименовал свои файлы в ConfigA.cs и ConfigB.cs

РЕДАКТИРОВАТЬ: (вежливость Кевин МакФит) Помните при переименовании файлов Configuration.cs, также переименуйте имена классов и конструкторы /EDIT

С помощью этой структуры вы можете просто сделать

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

Что создаст файлы кода для миграции внутри папки рядом с конфигурационными файлами (это хорошо, чтобы сохранить эти файлы вместе)

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

И последнее, но не менее важное: эти две команды будут применять правильные миграции для своих корневых баз данных.

РЕДАКТИРОВАТЬ 08 февраля 2016 года: Я провел небольшое тестирование с EF7 версии 7.0.0-rc1-16348

Я не мог использовать параметр -o | --outputDir. Он продолжал давать Microsoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument

Однако похоже, что при первом добавлении переноса он добавляется в папку Migrations, а последующая миграция для другого контекста автоматически помещается в поддокладчик миграции.

Оригинальные имена ContextA, похоже, нарушают некоторые соглашения об именах, поэтому теперь я использую ContextAContext и ContextBContext. Используя эти имена, вы можете использовать следующие команды: (обратите внимание, что мой dnx по-прежнему работает из консоли диспетчера пакетов, и я не люблю открывать отдельное окно CMD для миграции).

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

Это создаст моментальный снимок модели и начальную миграцию в папке Migrations для ContextAContext. Он создаст папку с именем ContextB, содержащую эти файлы для ContextBContext

Я вручную добавил папку ContextA и переместил файлы миграции из ContextAContext в эту папку. Затем я переименовал пространство имен внутри этих файлов (моментальный снимок, начальную миграцию и заметьте, что есть третий файл в файле начальной миграции... designer.cs). Мне пришлось добавить .ContextA в пространство имен, и оттуда фреймворк обработает его автоматически снова.

Использование следующих команд создаст новую миграцию для каждого контекста

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

и сгенерированные файлы помещаются в правильные папки.

Ответ 4

Если у вас уже есть "Конфигурация" со многими миграциями и вы хотите сохранить это как есть, вы всегда можете создать новый класс "Конфигурация" , дать ему другое имя, например

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

то просто введите команду

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

и EF без проблем справится с миграцией. Наконец, обновите свою базу данных, с этого момента EF будет жаловаться, если вы не скажете ему, какую конфигурацию вы хотите обновить:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Готово.

Вам не нужно иметь дело с Enable-Migrations, поскольку он будет жаловаться "Конфигурация" уже существует, и переименование существующего класса конфигурации приведет к проблемам в истории миграции.

Вы можете настроить таргетинг на разные базы данных или на одну и ту же, все конфигурации будут хорошо делиться таблицей __MigrationHistory.

Ответ 5

Если существует больше баз данных, используйте следующие коды в PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • "Стартер" - это миграционное имя

  • EnrollmentAppContext - это имя моего приложения. Контекст

Вы можете открыть PowerShell в VS, выполнив: Tools->NuGet Package Manager->Package Manager Console

Ответ 6

Чтобы обновить базу данных, введите следующие коды в PowerShell...

Update-Database -context EnrollmentAppContext

* если существует более одной базы данных, используйте только эти коды, в противном случае нет необходимости..

Ответ 7

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.