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


person aknuds1    schedule 20.11.2012    source источник


Ответы (7)


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

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

Update-Database -ConfigurationTypeName MyRenamedConfiguration
person ckal    schedule 20.11.2012
comment
Что такое MyRenamedConfiguration? - person Robert Noack; 15.06.2014
comment
MyRenamedConfiguration — это просто текст-заполнитель в качестве примера. Вы могли бы переименовать исходный файл Configuration.cs во что угодно (например, FooBar, а затем запустить Update-Database -ConfigurationTypeName FooBar). - person ckal; 16.06.2014
comment
сокращенная форма: Update-Database -conf MyRenamedConfiguration - person Peter Kerr; 08.11.2016

В дополнение к тому, что предложил @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. Команда Run

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

    or -

    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
    

    or -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
    
person Eric J.    schedule 28.01.2014
comment
Изменение #4: Редактировать ConfigurationA.cs -> Редактировать ConfigurationB.cs - person Brian Rizo; 06.03.2014
comment
@Biran: Спасибо, что заметили это. Я отредактировал ответ. Обратите внимание, что вы также можете редактировать ответы самостоятельно. Поскольку у вас еще нет репутации 2000, ваши ответы помещаются в очередь на проверку, но эта очередь обычно обрабатывается быстро, поэтому ваше редактирование, скорее всего, будет одобрено в течение нескольких минут. - person Eric J.; 07.03.2014
comment
СПАСИБО! Это то, чего мне не хватало (пространства имен). - person William M. Rawls; 16.08.2014
comment
Это может помочь, потому что изначально мне было непонятно, как выполнить переименование на шагах 2 и 4: когда вы переименовываете файл Configuration.cs в ConfigurationA.cs или ConfigurationB.cs, переименование также должно привести к переименованию класса и его конструктора в ConfigurationA или ConfigurationB. Если не переименовать класс, при выполнении команды add-migration появится сообщение об ошибке — Тип конфигурации миграции «ConfigurationA» не найден в сборке «...» — и да, формулировка была такой же плохой в сообщениях об ошибках, которые я получил в VS2013 - LOL - person Greg Barth; 20.01.2015
comment
@GregBarth: Спасибо, что указали на это. При переименовании файла в Visual Studio он также должен переименовать конструктор (если вы выбрали рефакторинг для соответствия переименованию). Я обновил текст, чтобы было понятнее. - person Eric J.; 20.01.2015
comment
это помогло мне! полная инструкция со всеми вариантами и порядком. сэкономил мне часы - person elcool; 08.09.2015
comment
Ссылки на переименование в посте и комментариях мне непонятны. В файле configuration.vb по умолчанию, созданном с помощью enable-migrations, есть миграция пространства имен и... конфигурация класса. Правильно ли отредактировать миграцию пространства именA и конфигурацию классаA? В третьем комментарии вверху говорится также переименовать конструктор, но конструктор уже называется New() (в VB) - кажется, что его не нужно переименовывать. - person Alan; 22.09.2015
comment
@Alan: В C# конструктор имеет то же имя, что и класс. Для каждой конфигурации требуется уникальное пространство имен. - person Eric J.; 22.09.2015
comment
@ЭрикДж. нужно сохранить папку миграции (Configuration.cs и...) после миграции и обновления полей базы данных??? - person AminM; 24.10.2017
comment
Если что-то может измениться в модели данных, то да. В следующий раз, когда среда выполнения обнаружит разницу между физической базой данных и тем, что требуется для текущей модели, она обратится к конфигурации, чтобы определить, как действовать дальше. Не вижу плюсов в удалении. - person Eric J.; 27.10.2017

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

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

EDIT: (любезно предоставлено Kevin McPheat) Помните, что при переименовании файлов Configuration.cs также переименовывайте имена классов и конструкторов /EDIT.

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

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

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

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

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

EDIT 08 Feb, 2016: я провел небольшое тестирование с EF7 версии 7.0.0-rc1-16348.

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

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

Первоначальные имена 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"

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

person bart s    schedule 07.10.2015
comment
лучшее решение, простое и мы держим четкую папку. - person Malick; 05.11.2015
comment
Это был тот ответ, который мне был нужен. Пространство имен, добавленное через -MigrationsDirectory, было ответом! Спасибо. - person Crob; 19.05.2016
comment
Хорошее и чистое решение. Спасибо. - person Stefan Cebulak; 13.11.2016
comment
Спустя 1,5 года я счастлив, что могу использовать свой собственный пост для настройки нового проекта. - person bart s; 19.04.2017
comment
Обратите внимание, что когда вы запускаете add-migration, вам будет предложено ввести Name. Это немного сбило меня с толку, так как я уже предоставлял ConfigurationTypeName и немного раздражался, когда он просто сказал Name:. Но, конечно, имя, которое он хочет, - это «удобочитаемое» описание изменения, например. AddedProducts или IncreaseLengthOfNameFields. В папке Migrations вы получите это как часть имени класса, чтобы было легко увидеть, что к чему. Таким образом, по сути, Name — это что-то вроде комментария регистрации. - person Simon_Weaver; 05.12.2017

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

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

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

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

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

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Сделанный.

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

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

person Guillermo Ruffino    schedule 24.05.2016

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

Add-Migration Starter -context EnrollmentAppContext 
  • «Стартер» — это имя миграции

  • «EnrollmentAppContext» — это имя контекста моего приложения.

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

person AHAMED AAQIB    schedule 12.03.2019

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

Update-Database -context EnrollmentAppContext

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

person AHAMED AAQIB    schedule 12.03.2019

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.
person Davit Mikuchadze    schedule 06.09.2019