Múltiplos contextos de banco de dados no mesmo banco de dados e aplicativo em migrações EF 6 e Code First

94

Sou novo no Entity Framework. Estou tentando configurar um aplicativo MVC que usa EF 6. Estou usando migrações de código primeiro. Estou usando o Areas no aplicativo e gostaria de ter diferentes DbContexts em cada área para separá-lo. Eu sei que EF 6 tem ContextKey, mas não consigo encontrar informações completas sobre como usá-lo. Atualmente, só posso usar as migrações em um contexto de cada vez.

Alguém pode dar um exemplo com detalhes suficientes para uma nova pessoa da EF como eu entender e usar.

Lrayh
fonte

Respostas:

176

O Entity Framework 6 adicionou suporte para vários DbContexts adicionando os sinalizadores -ContextTypeNamee -MigrationsDirectory. Acabei de executar os comandos em meu console do gerenciador de pacotes e colei a saída abaixo ...

Se você tiver 2 DbContexts em seu projeto e executá- enable-migrationslo, receberá um erro (como provavelmente já sabe):

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

Portanto, você deve executar enable-migrationscada um DbContextseparadamente. E você tem que especificar uma pasta para cada Configuration.csarquivo a ser gerado ...

PM> Enable-Migrations -ContextTypeName ApplicationDbContext -MigrationsDirectory Migrations\ApplicationDbContext
Checking if the context targets an existing database...
Code First Migrations enabled for project WebApplication3.

PM> Enable-Migrations -ContextTypeName AnotherDbContext -MigrationsDirectory Migrations\AnotherDbContext
Checking if the context targets an existing database...
Code First Migrations enabled for project WebApplication3.

Para adicionar migrações para cada um DbContext, faça assim, especificando o nome totalmente qualificado da Configurationclasse:

PM> Add-Migration -ConfigurationTypeName WebApplication3.Migrations.ApplicationDbContext.Configuration "InitialDatabaseCreation"
Scaffolding migration 'InitialDatabaseCreation'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration InitialDatabaseCreation' again.

PM> Add-Migration -ConfigurationTypeName WebApplication3.Migrations.AnotherDbContext.Configuration "InitialDatabaseCreation"
Scaffolding migration 'InitialDatabaseCreation'.
The Designer Code for this migration file includes a snapshot of your current Code First model. This snapshot is used to calculate the changes to your model when you scaffold the next migration. If you make additional changes to your model that you want to include in this migration, then you can re-scaffold it by running 'Add-Migration InitialDatabaseCreation' again.

E você corre update-databaseda mesma maneira:

PM> Update-Database -ConfigurationTypeName WebApplication3.Migrations.ApplicationDbContext.Configuration
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Applying explicit migrations: [201402032113124_InitialDatabaseCreation].
Applying explicit migration: 201402032113124_InitialDatabaseCreation.
Running Seed method.

PM> Update-Database -ConfigurationTypeName WebApplication3.Migrations.AnotherDbContext.Configuration
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
Applying explicit migrations: [201402032113383_InitialDatabaseCreation].
Applying explicit migration: 201402032113383_InitialDatabaseCreation.
Running Seed method.

Espero que isto ajude.

Anthony Chu
fonte
Preciso ter uma string de conexão separada para cada contexto ou existe uma maneira de contornar isso?
Lrayh
3
Eles podem compartilhar a mesma string de conexão. Mas você quer ter certeza de que eles não mapeiam para as mesmas tabelas.
Anthony Chu
Se eles mapearem para a mesma tabela, você ainda pode definir qual migração será executada primeiro e deixar seu arquivo de migração criar a tabela e qual será executado em segundo lugar e modificá-lo para que não crie a tabela já existente. Você pode então usar o MigrateDatabaseToLatestVersionforzing ctx.Database.initialize()de cada contexto para executar na ordem correta ou executar o Update-Databasecomando manualmente na ordem correta. (E o inverso, se você fizer uma migração de banco de dados para a versão anterior). É "perigoso", mas pode ser feito.
JotaBe
Então, adicionei migrações ao meu projeto e criei um contexto diferente de ApplicationDbContext. Passei a usar esse contexto, que eram dados relacionados ao site, por cerca de 6 meses, então chegou a hora de começar a mexer com meu ApplicationUser. Meu login e registro básicos estavam funcionando, mas eu queria estender a classe de usuário para adicionar alguns campos. Essa resposta foi muito útil para definir uma nova configuração de migração para esse contexto. Obrigado! # 1up
Eric Bishard
1
se eu puder te dar um +10 por esta resposta curta, mas mais do que suficiente, eu daria, Obrigado @AnthonyChu.
Karim AG