Bagaimana cara mengaktifkan migrasi EF untuk berbagai konteks untuk memisahkan database?

122

Bagaimana cara mengaktifkan migrasi Entity Framework 5 (versi 5.0.0) untuk beberapa konteks DB dalam proyek yang sama, di mana setiap konteks sesuai dengan database-nya sendiri? Ketika saya menjalankan Enable-Migrationsdi konsol PM (Visual Studio 2012), ada kesalahan karena terdapat beberapa konteks:

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.

Jika saya menjalankan, Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContextsaya tidak diizinkan untuk menjalankan Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContextkarena migrasi sudah ada:Migrations have already been enabled in project 'DatabaseService'. To overwrite the existing migrations configuration, use the -Force parameter.

aknuds1
sumber

Jawaban:

126

Panggilan kedua untuk Aktifkan-Migrasi gagal karena file Configuration.cs sudah ada. Jika Anda mengganti nama kelas dan file itu, Anda harus dapat menjalankan Enable-Migrations yang kedua, yang akan membuat Configuration.cs lain.

Anda kemudian perlu menentukan konfigurasi mana yang ingin Anda gunakan saat memperbarui database.

Update-Database -ConfigurationTypeName MyRenamedConfiguration
ckal
sumber
1
Apa itu "MyRenamedConfiguration"?
Robert Noack
1
"MyRenamedConfiguration" hanyalah teks placeholder sebagai contoh. Anda dapat mengubah nama Configuration.cs asli Anda menjadi apa pun, (mis. FooBar, lalu jalankan Update-Database -ConfigurationTypeName FooBar).
ckal
3
persingkat formulir: Perbarui-Database -conf MyRenamedConfiguration
Peter Kerr
100

Selain apa yang disarankan oleh @ckal, penting untuk memberi setiap Configuration.cs yang berganti nama, namespace sendiri. Jika tidak, EF akan mencoba menerapkan migrasi ke konteks yang salah.

Berikut adalah langkah-langkah spesifik yang berhasil bagi saya.

Jika Migrasi kacau dan Anda ingin membuat "baseline" baru:

  1. Hapus semua file .cs yang ada di folder Migrasi
  2. Di SSMS, hapus tabel sistem __MigrationHistory.

Membuat migrasi awal:

  1. Di Konsol Pengelola Paket:

    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
  2. Di Penjelajah Solusi: Ubah nama Migrations.Configuration.cs menjadi Migrations.ConfigurationA.cs. Ini akan secara otomatis mengganti nama konstruktor jika menggunakan Visual Studio. Pastikan ya. Edit ConfigurationA.cs: Ubah namespace ke NamespaceOfContext.Migrations.MigrationsA

  3. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
  4. Di Solution Explorer: Ubah nama Migrations.Configuration.cs menjadi Migrations.ConfigurationB.cs. Sekali lagi, pastikan konstruktor juga diganti namanya dengan benar. Edit ConfigurationB.cs: Ubah namespace ke 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

Langkah-langkah untuk membuat skrip migrasi di Package Manager Console:

  1. Jalankan perintah

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

    atau -

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

    Tidaklah mengapa untuk menjalankan kembali perintah ini sampai perubahan diterapkan ke DB.

  2. Jalankan skrip pada database lokal yang diinginkan, atau jalankan Update-Database tanpa -Script untuk diterapkan secara lokal:

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

    atau -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
Eric J.
sumber
# 4 perubahan: Edit ConfigurationA.cs -> Edit ConfigurationB.cs
Brian Rizo
1
@Biran: Terima kasih telah memperhatikan itu. Saya mengedit jawabannya. Perhatikan, Anda juga dapat mengedit jawaban sendiri. Karena Anda belum memiliki 2000 reputasi, jawaban Anda untuk antrean tinjauan tetapi antrian tersebut biasanya diproses dengan cepat, jadi pengeditan Anda kemungkinan besar akan disetujui dalam beberapa menit.
Eric J.
5
TERIMA KASIH! Itulah yang saya lewatkan (ruang nama).
William M. Rawls
Ini dapat membantu karena tidak jelas bagi saya bagaimana melakukan penggantian nama pada langkah 2, dan 4 pada awalnya: Saat Anda mengganti nama file Configuration.cs menjadi ConfigurationA.cs atau ConfigurationB.cs, penggantian nama juga harus menghasilkan class dan konstruktornya diubah namanya menjadi ConfigurationA atau ConfigurationB juga. Kegagalan untuk mengganti nama kelas akan menyebabkan pesan kesalahan ketika Anda menjalankan perintah tambahkan-migrasi - "Jenis konfigurasi migrasi 'ConfigurationA' tidak ditemukan di perakitan '...'" - dan ya, kata-katanya buruk seperti bahwa dalam pesan kesalahan yang saya dapatkan di VS2013 - LOL
Greg Barth
3
ini membantu saya! instruksi lengkap dengan semua opsi dan pesanan. menyelamatkan saya berjam-jam
elcool
82

Saya baru saja mengalami masalah yang sama dan saya menggunakan solusi berikut (semua dari Package Manager Console)

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

Ini akan membuat 2 folder terpisah di folder Migrasi. Masing-masing akan berisi Configuration.csfile yang dihasilkan . Sayangnya Anda masih harus mengganti nama Configuration.csfile tersebut jika tidak akan ada keluhan tentang memiliki dua di antaranya. Saya mengganti nama file saya menjadi ConfigA.csdanConfigB.cs

EDIT : (courtesy Kevin McPheat) Ingat saat mengganti nama file Configuration.cs, juga ganti nama kelas dan konstruktor / EDIT

Dengan struktur ini Anda bisa langsung melakukannya

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

Yang akan membuat file kode untuk migrasi di dalam folder di sebelah file konfigurasi (ini bagus untuk menyimpan file-file itu bersama-sama)

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

Dan yang tak kalah pentingnya kedua perintah itu akan menerapkan migrasi yang benar ke database yang sesuai.

EDIT 08 Feb, 2016: Saya telah melakukan sedikit pengujian dengan EF7 versi 7.0.0-rc1-16348

Saya tidak bisa mengaktifkan opsi -o | --outputDir. Itu terus memberiMicrosoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument

Namun tampaknya saat pertama kali ditambahkan, migrasi ditambahkan ke folder Migrasi, dan migrasi berikutnya untuk konteks lain secara otomatis dimasukkan ke dalam subdolder migrasi.

Nama asli ContextAsepertinya melanggar beberapa konvensi penamaan jadi sekarang saya menggunakan ContextAContextdan ContextBContext. Dengan menggunakan nama-nama ini, Anda dapat menggunakan perintah berikut: (perhatikan bahwa dnx saya masih berfungsi dari konsol manajer paket dan saya tidak suka membuka jendela CMD terpisah untuk melakukan migrasi)

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

Ini akan membuat snapshot model dan migrasi awal di Migrationsfolder untuk ContextAContext. Ini akan membuat folder bernama yang ContextBberisi file-file ini untukContextBContext

Saya menambahkan ContextAfolder secara manual dan memindahkan file migrasi dariContextAContext ke folder itu. Kemudian saya mengganti nama namespace di dalam file-file itu (file snapshot, migrasi awal dan perhatikan bahwa ada file ketiga di bawah file migrasi awal ... designer.cs). Saya harus menambahkan .ContextAnamespace, dan dari sana framework menanganinya secara otomatis lagi.

Menggunakan perintah berikut akan membuat migrasi baru untuk setiap konteks

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

dan file yang dihasilkan disimpan di folder yang benar.

bart s
sumber
5
solusi terbaik, sederhana dan kami menyimpan folder yang jelas.
Malick
2
Ini adalah jawaban yang saya butuhkan. Namespace yang ditambahkan melalui -MigrationsDirectory adalah jawabannya! Terima kasih.
Crob
1
Solusi bagus dan bersih. Terima kasih.
Stefan Cebulak
4
1,5 tahun kemudian, saya senang bahwa saya dapat menggunakan posting saya sendiri untuk menyiapkan proyek baru.
bart
1
Catatan ketika Anda menjalankannya add-migrationakan meminta Anda untuk Name. Ini membuat saya ConfigurationTypeNamesedikit tersinggung karena saya sudah menyediakan dan menjadi sedikit kesal ketika baru saja dikatakan Name:. Tapi tentu saja Nama yang diinginkannya adalah deskripsi perubahan yang 'dapat dibaca manusia' - mis. AddedProductsatau IncreaseLengthOfNameFields. Di folder Migration Anda akan mendapatkan ini sebagai bagian dari nama kelas sehingga mudah untuk melihat apa itu. Jadi, efeknya Nameseperti komentar check-in.
Simon_Weaver
7

Jika Anda sudah memiliki "Konfigurasi" dengan banyak migrasi dan ingin tetap seperti ini, Anda selalu dapat membuat kelas "Konfigurasi" baru, beri nama lain, seperti

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

lalu berikan perintah saja

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

dan EF akan mengatur migrasi tanpa masalah. Terakhir perbarui database Anda, mulai sekarang, EF akan mengeluh jika Anda tidak memberi tahu dia konfigurasi mana yang ingin Anda perbarui:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Selesai.

Anda tidak perlu berurusan dengan Aktifkan-Migrasi karena akan mengeluh "Konfigurasi" sudah ada, dan mengganti nama kelas Konfigurasi yang ada akan membawa masalah pada riwayat migrasi.

Anda dapat menargetkan database yang berbeda, atau database yang sama, semua konfigurasi akan berbagi tabel __MigrationHistory dengan baik.

Guillermo Ruffino
sumber
4

Jika ada lebih banyak database, gunakan kode berikut di PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • 'Pemula' adalah Nama Migrasi

  • 'EnrollmentAppContext' adalah nama Konteks aplikasi saya

Anda dapat membuka PowerShell di VS dengan melakukan: Tools->NuGet Package Manager->Package Manager Console

AHAMED AAQIB
sumber
1
Ini membantu saya. Terima kasih! :)
noobprogrammer
3

Untuk memperbarui tipe database kode berikut di PowerShell ...

Update-Database -context EnrollmentAppContext

* Jika ada lebih dari satu database, gunakan hanya kode ini, jika tidak, tidak perlu ..

AHAMED AAQIB
sumber
0

EF 4.7 sebenarnya memberi petunjuk saat Anda menjalankan Enable-migrations di berbagai konteks.

Lebih dari satu jenis konteks ditemukan di rakitan '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.
Davit Mikuchadze
sumber