ฉันจะเปิดใช้งานการโอนย้าย EF สำหรับหลายบริบทเพื่อแยกฐานข้อมูลได้อย่างไร


122

ฉันจะเปิดใช้งานการโอนย้าย Entity Framework 5 (เวอร์ชัน 5.0.0) สำหรับบริบท DB หลายรายการในโครงการเดียวกันได้อย่างไรโดยที่แต่ละบริบทสอดคล้องกับฐานข้อมูลของตนเอง เมื่อฉันรัน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.


คำตอบ:


126

การเรียกครั้งที่ 2 เพื่อเปิดใช้งานการโยกย้ายล้มเหลวเนื่องจากมีไฟล์ Configuration.cs อยู่แล้ว หากคุณเปลี่ยนชื่อคลาสและไฟล์นั้นคุณควรจะสามารถเรียกใช้การเปิดใช้งานการโยกย้ายครั้งที่ 2 ซึ่งจะสร้าง Configuration.cs ขึ้นมาใหม่

จากนั้นคุณจะต้องระบุการกำหนดค่าที่คุณต้องการใช้เมื่ออัปเดตฐานข้อมูล

Update-Database -ConfigurationTypeName MyRenamedConfiguration

1
"MyRenamedConfiguration" คืออะไร?
Robert Noack

1
"MyRenamedConfiguration" เป็นเพียงตัวยึดข้อความดังตัวอย่าง คุณสามารถเปลี่ยนชื่อ Configuration.cs เดิมของคุณเป็นอะไรก็ได้ (เช่น FooBar จากนั้นเรียกใช้ Update-Database -ConfigurationTypeName FooBar)
ckal

3
ย่อรูปแบบ: Update-Database -conf MyRenamedConfiguration
Peter Kerr

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. ใน Solution Explorer: เปลี่ยนชื่อ 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. ใน Solution Explorer: เปลี่ยนชื่อ 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

ขั้นตอนในการสร้างสคริปต์การโอนย้ายใน Package Manager Console:

  1. เรียกใช้คำสั่ง

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

    หรือ -

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

    สามารถรันคำสั่งนี้ซ้ำได้จนกว่าการเปลี่ยนแปลงจะถูกนำไปใช้กับ DB

  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: แก้ไข ConfigurationA.cs -> แก้ไข ConfigurationB.cs
Brian Rizo

1
@ Biran: ขอบคุณที่สังเกตเห็น ฉันแก้ไขคำตอบ หมายเหตุคุณสามารถแก้ไขคำตอบด้วยตัวเองได้เช่นกัน เนื่องจากคุณยังไม่มีชื่อเสียงในปี 2000 คำตอบของคุณในคิวการตรวจสอบ แต่โดยปกติแล้วคิวนั้นจะทำงานได้อย่างรวดเร็วดังนั้นการแก้ไขของคุณน่าจะได้รับการอนุมัติภายในไม่กี่นาที
Eric J.

5
ขอบคุณ! นั่นคือสิ่งที่ฉันขาดหายไป (เนมสเปซ)
William M. Rawls

สิ่งนี้อาจช่วยได้เนื่องจากฉันไม่ทราบวิธีการเปลี่ยนชื่อในขั้นตอนที่ 2 และ 4ในตอนแรก: เมื่อคุณเปลี่ยนชื่อไฟล์ Configuration.cs เป็น ConfigurationA.cs หรือ ConfigurationB.cs การเปลี่ยนชื่อควรส่งผลให้คลาสและ คอนสตรัคเตอร์ถูกเปลี่ยนชื่อเป็น ConfigurationA หรือ ConfigurationB ด้วย ความล้มเหลวในการเปลี่ยนชื่อคลาสจะทำให้เกิดข้อความแสดงข้อผิดพลาดเมื่อคุณเรียกใช้คำสั่ง add-migration - "ไม่พบประเภทการกำหนดค่าการย้ายข้อมูล" ConfigurationA "ในแอสเซมบลี" ... " - และใช่ข้อความไม่ถูกต้องเช่นเดียวกับ ว่าในข้อความแสดงข้อผิดพลาดที่ฉันได้รับใน VS2013 - LOL
Greg Barth

3
สิ่งนี้ช่วยฉันได้! คำแนะนำที่สมบูรณ์พร้อมตัวเลือกและคำสั่งซื้อทั้งหมด ช่วยฉันได้หลายชั่วโมง
elcool

82

ฉันเพิ่งพบปัญหาเดียวกันและฉันใช้วิธีแก้ปัญหาต่อไปนี้ (ทั้งหมดจากคอนโซล Package Manager)

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

แก้ไข : (มารยาท Kevin McPheat) โปรดจำไว้ว่าเมื่อเปลี่ยนชื่อไฟล์ Configuration.cs เปลี่ยนชื่อคลาสและตัวสร้าง/ แก้ไข

ด้วยโครงสร้างนี้คุณสามารถทำได้

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

ซึ่งจะสร้างไฟล์โค้ดสำหรับการย้ายข้อมูลภายในโฟลเดอร์ถัดจากไฟล์กำหนดค่า (นี่เป็นการดีที่จะเก็บไฟล์เหล่านั้นไว้ด้วยกัน)

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

และสุดท้าย แต่ไม่ท้ายสุดทั้งสองคำสั่งจะใช้การย้ายข้อมูลที่ถูกต้องกับฐานข้อมูลการตอบสนองของตน

แก้ไข 08 ก.พ. 2559: ฉันได้ทำการทดสอบกับ 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
ทางออกที่ดีที่สุดง่ายและเก็บโฟลเดอร์ที่ชัดเจน
Malick

2
นี่คือคำตอบที่ฉันต้องการ เนมสเปซที่เพิ่มผ่าน -MigrationsDirectory คือคำตอบ! ขอบคุณ.
Crob

1
ทางออกที่ดีและสะอาด ขอบคุณ
Stefan Cebulak

4
1,5 ปีต่อมาฉันมีความสุขที่สามารถใช้โพสต์ของตัวเองเพื่อสร้างโปรเจ็กต์ใหม่
bart

1
หมายเหตุเมื่อคุณเรียกใช้add-migrationระบบจะแจ้งให้คุณNameทราบ นี้โยนฉันลงเล็กน้อยตั้งแต่ฉันได้แล้วให้และได้รำคาญเล็กน้อยเมื่อมันก็กล่าวว่าConfigurationTypeName Name:แต่แน่นอนว่าชื่อที่ต้องการคือคำอธิบายที่ 'มนุษย์อ่านได้' ของการเปลี่ยนแปลง - เช่น AddedProductsหรือIncreaseLengthOfNameFields. ในโฟลเดอร์ Migrations คุณจะได้รับสิ่งนี้เป็นส่วนหนึ่งของชื่อคลาสเพื่อให้ง่ายต่อการดูว่าอะไรคืออะไร ผลNameก็เหมือนกับความคิดเห็นในการเช็คอิน
Simon_Weaver

7

ในกรณีที่คุณมี "การกำหนดค่า" ที่มีการย้ายข้อมูลจำนวนมากและต้องการคงไว้เช่นเดิมคุณสามารถสร้างคลาส "การกำหนดค่า" ใหม่ได้ตลอดเวลาโดยตั้งชื่ออื่นเช่น

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

จากนั้นออกคำสั่ง

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

และ EF จะนั่งร้านการโยกย้ายโดยไม่มีปัญหา สุดท้ายอัปเดตฐานข้อมูลของคุณนับจากนี้ EF จะบ่นหากคุณไม่บอกเขาว่าต้องการอัปเดตการกำหนดค่าใด:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

เสร็จสิ้น

คุณไม่จำเป็นต้องจัดการกับ Enable-Migrations เนื่องจากจะบ่นว่ามี "Configuration" อยู่แล้วและการเปลี่ยนชื่อคลาส Configuration ที่มีอยู่ของคุณจะทำให้เกิดปัญหาในประวัติการย้ายข้อมูล

คุณสามารถกำหนดเป้าหมายฐานข้อมูลที่แตกต่างกันหรือฐานข้อมูลเดียวกันการกำหนดค่าทั้งหมดจะแชร์ตาราง __MigrationHistory อย่างสวยงาม


4

หากมีฐานข้อมูลเพิ่มเติมให้ใช้รหัสต่อไปนี้ใน PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • 'Starter' คือชื่อการย้ายข้อมูล

  • '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.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.