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

122

Как включить миграцию 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.

aknuds1
источник

Ответы:

126

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

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

Update-Database -ConfigurationTypeName MyRenamedConfiguration
ckal
источник
1
Что такое MyRenamedConfiguration?
Роберт Ноак
1
«MyRenamedConfiguration» - это просто текст-заполнитель в качестве примера. Вы могли бы переименовать исходный файл Configuration.cs во что угодно (например, FooBar, затем запустить Update-Database -ConfigurationTypeName FooBar).
ckal
3
сокращенная форма: Update-Database -conf MyRenamedConfiguration
Питер Керр
100

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

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

Если с миграциями произошла ошибка, и вы хотите создать новую «базовую линию»:

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

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

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

    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
  2. В обозревателе решений: переименуйте Migrations.Configuration.cs в Migrations.ConfigurationA.cs. Это должно автоматически переименовать конструктор при использовании Visual Studio. Убедитесь, что это так. Изменить ConfigurationA.cs: измените пространство имен на NamespaceOfContext.Migrations.MigrationsA

  3. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
  4. В обозревателе решений: переименуйте Migrations.Configuration.cs в Migrations.ConfigurationB.cs. Опять же, убедитесь, что конструктор также переименован соответствующим образом. Изменить ConfigurationB.cs: измените пространство имен на NamespaceOfContext.Migrations.MigrationsB

  5. add-migration InitialBSchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB 
  6. Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
  7. add-migration InitialSurveySchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationA -ProjectName ProjectContextIsInIfNotMainOne -StartupProjectName
    NameOfMainProject  -ConnectionStringName ContextA 
  8. Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA

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

  1. Команда выполнения

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

    или -

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

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

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

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

    или -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
Эрик Дж.
источник
# 4 изменение: Edit ConfigurationA.cs -> Edit ConfigurationB.cs
Брайан Ризо
1
@Biran: Спасибо, что заметили это. Я отредактировал ответ. Учтите, что вы тоже можете редактировать ответы самостоятельно. Поскольку у вас еще нет репутации 2000, ваши ответы на вопрос помещаются в очередь на рассмотрение, но эта очередь обычно обрабатывается быстро, поэтому ваше изменение, вероятно, будет одобрено в течение нескольких минут.
Эрик Дж.
5
СПАСИБО! Вот чего мне не хватало (пространств имен).
Уильям М. Ролз
Это может помочь, потому что мне было непонятно, как выполнить переименование на шагах 2 и 4 изначально: когда вы переименовываете файл Configuration.cs в ConfigurationA.cs или ConfigurationB.cs, переименование также должно приводить к классу и его конструктор также переименован в ConfigurationA или ConfigurationB. Неспособность переименовать класс вызовет сообщение об ошибке при запуске команды add-migration - «Тип конфигурации миграции 'ConfigurationA' не найден в сборке '...'» - и да, формулировка была плохой, как и это в сообщениях об ошибках, которые я получил в VS2013 - LOL
Грег Барт
3
это мне помогло! Полная инструкция со всеми опциями и порядком. сэкономил мне часы
elcool 08
82

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

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

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

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

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

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"

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

Барт с
источник
5
лучшее решение, простое и чистая папка.
Малик
2
Это был ответ, который мне был нужен. Пространство имен, добавленное через -MigrationsDirectory, было ответом! Спасибо.
Crob
1
Красивое и чистое решение. Спасибо.
Стефан Чебулак
4
1,5 года спустя я счастлив, что могу использовать свой собственный пост для создания нового проекта.
bart s
1
Обратите внимание, что при запуске add-migrationвам будет предложено ввести Name. Это меня немного сбило с толку, так как я уже предоставлял, ConfigurationTypeNameи немного раздражался, когда он только что сказал Name:. Но, конечно, имя, которое он хочет, - это «удобочитаемое» описание изменения - например. AddedProductsили IncreaseLengthOfNameFields. В папке Migrations вы получите это как часть имени класса, чтобы было легко увидеть, что к чему. По сути, Nameэто похоже на комментарий о регистрации.
Simon_Weaver 05
7

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

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

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

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

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

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Готово.

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

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

Гильермо Руффино
источник
4

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

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

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

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

АХАМЕД ААКИБ
источник
1
Это мне помогло. Спасибо! :)
noobprogrammer
3

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

Update-Database -context EnrollmentAppContext

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

АХАМЕД ААКИБ
источник
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.
Давид Микучадзе
источник