Entity Framework rollback và loại bỏ di chuyển xấu


174

Tôi đang sử dụng EF 6.0 cho dự án của mình trong C # với các bản cập nhật và di chuyển thủ công. Tôi có khoảng 5 lần di chuyển trên cơ sở dữ liệu, nhưng tôi nhận ra rằng lần di chuyển cuối cùng là xấu và tôi không muốn điều đó. Tôi biết rằng tôi có thể quay trở lại di chuyển trước đó, nhưng khi tôi thêm di chuyển (cố định) mới và chạy Cập nhật cơ sở dữ liệu, ngay cả di chuyển xấu cũng được áp dụng.

Tôi đã cố gắng quay trở lại di chuyển trước đó và xóa các tập tin với di chuyển xấu. Nhưng sau đó, khi tôi cố gắng thêm di chuyển mới, tôi gặp lỗi khi cập nhật cơ sở dữ liệu, vì tệp di chuyển bị hỏng (cụ thể hơn, dòng mã đầu tiên đổi tên bảng A thành B và là dòng tiếp theo, EF đang cố cập nhật bảng với tên A - có thể đó là một số lỗi của EF).

Có một số truy vấn tôi có thể chạy, nó sẽ nói với EF một cái gì đó như "Quên di chuyển lần cuối như chưa từng tồn tại, nó rất tệ"? Một cái gì đó như Xóa-Di chuyển.

Edit1 Tôi tìm thấy giải pháp phù hợp với tôi. Thay đổi mô hình sang trạng thái tốt và chạy Add-Migration TheBadMigration -Force. Điều này sẽ tái giàn giáo lần cuối, không áp dụng di chuyển.

Dù sao, điều này vẫn không trả lời hoàn toàn câu hỏi ban đầu. Nếu tôi Cập nhật Cơ sở dữ liệu cho việc di chuyển xấu, tôi đã không tìm thấy cách tốt để quay lại và tạo di chuyển mới, ngoại trừ di chuyển xấu.

Cảm ơn


Tôi đã phải khởi động lại studio hình ảnh và sau đó nó bắt đầu hoạt động đúng. Điều này đã xảy ra một vài lần với tôi, luôn luôn sau khi loay hoay với việc di chuyển mà không thực sự cập nhật cơ sở dữ liệu, vì vậy có điều gì đó kỳ lạ xảy ra với công cụ ở đó.
Andrei Dvoynos

Câu trả lời:


167

Bạn có 2 lựa chọn:

  • Bạn có thể lấy Down từ di chuyển xấu và đưa nó vào một di chuyển mới (bạn cũng sẽ cần thực hiện các thay đổi tiếp theo cho mô hình). Đây là hiệu quả cuộn lên một phiên bản tốt hơn.

    Tôi sử dụng tùy chọn này cho những thứ đã đi đến nhiều môi trường.

  • Tùy chọn khác là thực sự chạy Update-Database –TargetMigration: TheLastGoodMigrationvới cơ sở dữ liệu đã triển khai của bạn và sau đó xóa di chuyển khỏi giải pháp của bạn. Đây là một sự thay thế hulk smash và yêu cầu điều này phải được thực hiện đối với bất kỳ cơ sở dữ liệu nào được triển khai với phiên bản xấu.

    Lưu ý: để hủy bỏ việc di chuyển mà bạn có thể sử dụng Add-Migration [existingname] -Force. Tuy nhiên, điều này sẽ ghi đè di chuyển hiện tại của bạn, vì vậy hãy chắc chắn chỉ thực hiện việc này nếu bạn đã xóa di chuyển hiện tại khỏi cơ sở dữ liệu. Điều này thực hiện tương tự như xóa tệp di chuyển hiện có và chạyadd-migration

    Tôi sử dụng tùy chọn này trong khi phát triển.


1
Tùy chọn đập hulk không hoạt động. Tôi chưa áp dụng di chuyển xấu vào cơ sở dữ liệu. Tôi đã thử, nhưng nó không hoạt động, vì tên bảng tôi đã chỉ định trong câu hỏi ban đầu. Tùy chọn đầu tiên tôi không thích nhiều, vì có vẻ như tôi sẽ phải thay đổi mã di chuyển. Nếu tôi làm nó kém, tôi có thể phá vỡ tất cả.
Martin Brabec

8
Nếu bạn chưa áp dụng việc di chuyển xấu thì không có gì ngăn cản bạn xóa nó và hủy bỏ hoặc sửa chữa di chuyển bị hỏng.
Không yêu

4
'Hulk smash' là câu trả lời, nó hoạt động với tôi khi phát triển và tôi muốn thêm một cái gì đó vào việc di chuyển mà tôi đã bỏ lỡ. Tôi nghĩ rằng những lý do nó không hoạt động đối với Martin không liên quan (hoặc có thể liên quan đến việc thay đổi lược đồ cơ sở dữ liệu theo cách thủ công)
rethenhouser2

1
@BenRethmeier như một quy tắc chung Tôi chỉ sử dụng tùy chọn đập vỡ hulk khi tôi đang phát triển. Trong prod tôi luôn tạo một di chuyển mới để khắc phục vấn đề. Lý do là bạn cần can thiệp thủ công nếu bạn đang hạ cấp cơ sở dữ liệu. Tôi không thích bất cứ điều gì cần can thiệp thủ công trong prod.
Không yêu

1
HULK SMASH !!!! --- Tôi đã cố gắng làm tốt nhưng EF không chơi - Tôi đã hoàn nguyên về lần cuối được biết đến - (Đã sao lưu các tệp di chuyển) Đã xóa, Đã thêm Di chuyển - Buộc - Đổi tên thành trước đó và sao chép mã. Cơ sở dữ liệu cập nhật sau đó đã thêm di chuyển thứ hai theo cùng một cách - không có lỗi - trở lại bình thường
Traci

127

Như câu hỏi chỉ ra điều này áp dụng cho việc di chuyển trong môi trường loại phát triển chưa được phát hành.

Vấn đề này có thể được giải quyết trong các bước sau: khôi phục cơ sở dữ liệu của bạn về lần di chuyển tốt cuối cùng, xóa di chuyển xấu khỏi dự án Entity Framework của bạn, tạo một di chuyển mới và áp dụng nó vào cơ sở dữ liệu. Lưu ý: Đánh giá từ các bình luận, các lệnh chính xác này có thể không còn được áp dụng nếu bạn đang sử dụng EF Core.

Bước 1: Khôi phục lại quá trình di chuyển trước đó

Nếu bạn chưa áp dụng di chuyển của mình, bạn có thể bỏ qua phần này. Để khôi phục lược đồ cơ sở dữ liệu của bạn về vấn đề điểm trước đó, lệnh Update-Database với tùy chọn -TargetMigration chỉ định di chuyển tốt cuối cùng. Nếu mã khung thực thể của bạn nằm trong một dự án khác trong giải pháp của bạn, bạn có thể cần sử dụng tùy chọn 'Dự án' hoặc chuyển đổi dự án mặc định trong bảng điều khiển trình quản lý gói.

Update-Database TargetMigration: <name of last good migration>

Để có được tên của lần di chuyển tốt cuối cùng, hãy sử dụng lệnh 'Nhận di chuyển' để truy xuất danh sách các tên di chuyển đã được áp dụng cho cơ sở dữ liệu của bạn.

PM> Get-Migrations
Retrieving migrations that have been applied to the target database.
201508242303096_Bad_Migration
201508211842590_The_Migration_applied_before_it
201508211440252_And_another

Danh sách này hiển thị các di chuyển được áp dụng gần đây nhất đầu tiên. Chọn di chuyển xảy ra trong danh sách sau khi di chuyển bạn muốn hạ cấp, tức là di chuyển được áp dụng trước khi di chuyển bạn muốn hạ cấp. Bây giờ phát hành một cơ sở dữ liệu cập nhật.

Update-Database TargetMigration: "<the migration applied before it>"

Tất cả các lần di chuyển được áp dụng sau một lần di chuyển được chỉ định sẽ được giảm điểm theo thứ tự bắt đầu với lần di chuyển mới nhất được áp dụng trước.

Bước 2: Xóa di chuyển của bạn khỏi dự án

remove-migration name_of_bad_migration

Nếu remove-migrationlệnh không có sẵn trong phiên bản Entity Framework của bạn, hãy xóa các tệp của di chuyển không mong muốn thư mục 'Di chuyển' của dự án EF của bạn theo cách thủ công. Tại thời điểm này, bạn có thể tự do tạo một di chuyển mới và áp dụng nó vào cơ sở dữ liệu.

Bước 3: Thêm di chuyển mới của bạn

add-migration my_new_migration

Bước 4: Áp dụng di chuyển của bạn vào cơ sở dữ liệu

update-database

6
Với EF Core, có vẻ như Get-Migration đã bị xóa.
Kevin Burton

1
Bước 2 ! - Tính năng rất hữu ích. Như @KevinBurton đã đề cập. Và sau đó add-migration "new migration",update-database
Alexander Frolov

2
Cập nhật cơ sở dữ liệu cơ sở dữ liệu: "<di chuyển được áp dụng trước đó>" @David Sopko
Fuat

Cảm ơn @AlexanderFrolov Tôi đã cập nhật giải pháp để phản ánh ý kiến ​​của bạn.
David Sopko

1
chúng ta cần sử dụng loại bỏ di chuyển sau bước 2
Rahul

55

Đối với những người sử dụng EF Core với ASP.NET Core v1.0.0, tôi gặp vấn đề tương tự và đã sử dụng các lệnh sau để sửa lỗi (bài đăng của @ DavidSopko đã chỉ cho tôi đi đúng hướng, nhưng các chi tiết hơi khác so với EF Core) :

Update-Database <Name of last good migration>
Remove-Migration

Ví dụ, trong sự phát triển hiện tại của tôi, lệnh đã trở thành

PM> Update-Database CreateInitialDatabase
Done.
PM> Remove-Migration
Done.
PM> 

Xóa di chuyển sẽ xóa di chuyển cuối cùng bạn đã áp dụng. Nếu bạn có một kịch bản phức tạp hơn với nhiều lần di chuyển để loại bỏ (tôi chỉ có 2, lần đầu tiên và kịch bản xấu), tôi khuyên bạn nên kiểm tra các bước trong một dự án giả.

Hiện tại dường như không có lệnh Nhận di chuyển trong EF Core (v1.0.0), do đó bạn phải xem trong thư mục di chuyển của mình và làm quen với những gì bạn đã làm. Tuy nhiên, có một lệnh trợ giúp tốt đẹp:

PM> get-help entityframework

Làm mới cơ sở dữ liệu dastabase trong VS2015 SQL Server Object Explorer, tất cả dữ liệu của tôi đã được bảo tồn và quá trình di chuyển mà tôi muốn hoàn nguyên đã biến mất :)

Ban đầu, tôi đã thử tự gỡ bỏ Di chuyển và thấy lệnh lỗi khó hiểu:

System.InvalidOperationException: Di chuyển '...' đã được áp dụng cho cơ sở dữ liệu. Không vui và thử lại. Nếu di chuyển đã được áp dụng cho các cơ sở dữ liệu khác, hãy xem xét hoàn nguyên các thay đổi của nó bằng cách sử dụng di chuyển mới.

Đã có đề xuất về việc cải thiện từ ngữ này, nhưng tôi muốn lỗi khi nói điều gì đó như thế này:

Chạy Update-Database (tên di chuyển tốt cuối cùng) để hoàn nguyên lược đồ cơ sở dữ liệu về trạng thái đó. Lệnh này sẽ không hài lòng tất cả các lần di chuyển xảy ra sau khi di chuyển được chỉ định cho Cơ sở dữ liệu cập nhật. Sau đó, bạn có thể chạy Xóa-Di chuyển (tên di chuyển để xóa)

Đầu ra từ lệnh trợ giúp của EF Core như sau:

 PM> get-help entityframework
                     _/\__
               ---==/    \\
         ___  ___   |.    \|\
        | __|| __|  |  )   \\\
        | _| | _|   \_/ |  //|\\
        |___||_|       /   \\\/\\

TOPIC
    about_EntityFrameworkCore

SHORT DESCRIPTION
    Provides information about Entity Framework Core commands.

LONG DESCRIPTION
    This topic describes the Entity Framework Core commands. See https://docs.efproject.net for information on Entity Framework Core.

    The following Entity Framework cmdlets are included.

        Cmdlet                      Description
        --------------------------  ---------------------------------------------------
        Add-Migration               Adds a new migration.

        Remove-Migration            Removes the last migration.

        Scaffold-DbContext          Scaffolds a DbContext and entity type classes for a specified database.

        Script-Migration            Generates a SQL script from migrations.

        Update-Database             Updates the database to a specified migration.

        Use-DbContext               Sets the default DbContext to use.

SEE ALSO
    Add-Migration
    Remove-Migration
    Scaffold-DbContext
    Script-Migration
    Update-Database
    Use-DbContext

6

Bạn cũng có thể dùng

Remove-Migration -Force

Điều này sẽ hoàn nguyên và loại bỏ di chuyển được áp dụng cuối cùng


4

Đầu tiên, Cập nhật di chuyển hoàn hảo cuối cùng của bạn thông qua lệnh này:

Update-Database TargetMigration

Thí dụ:

Update-Database -20180906131107_xxxx_xxxx

Và, sau đó xóa di chuyển không sử dụng của bạn bằng tay.


2
cần là: Cập nhật-Cơ sở dữ liệu -TargetMigration 20180906131107_xxxx_xxxx
Elger Mensonides 19/12/18

Update-Database 20180906131107_xxxx_xxxx(không có dấu gạch ngang) làm việc cho tôi. Không có phiên bản TargetMigrationnhư một công tắc làm việc. Các lệnh này dường như là một mục tiêu di động (tức là thay đổi chúng trong mọi phiên bản)?
Tổng hợp Không có

3

Kể từ .NET Core 2.2, TargetMigrationdường như không còn nữa:

get-help Update-Database

NAME
    Update-Database

SYNOPSIS
    Updates the database to a specified migration.


SYNTAX
    Update-Database [[-Migration] <String>] [-Context <String>] [-Project <String>] [-StartupProject <String>] [<CommonParameters>]


DESCRIPTION
    Updates the database to a specified migration.


RELATED LINKS
    Script-Migration
    about_EntityFrameworkCore 

REMARKS
    To see the examples, type: "get-help Update-Database -examples".
    For more information, type: "get-help Update-Database -detailed".
    For technical information, type: "get-help Update-Database -full".
    For online help, type: "get-help Update-Database -online"

Vì vậy, điều này làm việc cho tôi bây giờ:

Update-Database -Migration 20180906131107_xxxx_xxxx

Cũng như (không có -Migrationcông tắc):

Update-Database 20180906131107_xxxx_xxxx

Trên một ghi chú được thêm vào, bạn không còn có thể xóa sạch các thư mục di chuyển mà không đặt Ảnh chụp mô hình của bạn không đồng bộ. Vì vậy, nếu bạn học được điều này một cách khó khăn và kết thúc với một di chuyển trống nơi bạn biết sẽ có thay đổi, bạn có thể chạy (không cần chuyển đổi cho lần di chuyển cuối cùng):

Remove-migration

Nó sẽ dọn dẹp mớ hỗn độn và đưa bạn trở lại nơi bạn cần, mặc dù thư mục di chuyển cuối cùng đã bị xóa thủ công.


0

Đối với EF 6 đây là một lớp lót nếu bạn đang dàn dựng lại rất nhiều trong quá trình phát triển. Chỉ cần cập nhật các vars và sau đó tiếp tục sử dụng mũi tên lên trong bảng điều khiển trình quản lý gói để rửa và lặp lại.

$lastGoodTarget = "OldTargetName"; $newTarget = "NewTargetName"; Update-Database -TargetMigration "$lastGoodTarget" -Verbose; Add-Migration "$newTarget" -Verbose -Force

Tại sao điều này cần thiết bạn yêu cầu? Không chắc chắn phiên bản nào của EF6 này áp dụng nhưng nếu mục tiêu di chuyển mới của bạn đã được áp dụng thì sử dụng '-Force' để tái tạo lại giàn giáo trong Thêm di chuyển sẽ không thực sự tái tạo giàn giáo, nhưng thay vào đó hãy tạo một tệp mới (đây là một tệp tốt mặc dù vì bạn sẽ không muốn mất 'Xuống'). Đoạn mã trên thực hiện 'Xuống' trước nếu cần thiết sau đó -Force hoạt động chính xác để tái tạo giàn giáo.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.