21

Tôi đã xây dựng một ứng dụng demo WPF nhỏ sử dụng EF Code-First để lưu dữ liệu của nó trong một SQL CE 4.0 DB. Nó hoạt động tốt trừ khi tôi loại bỏ một thuộc tính từ một đối tượng mô hình. Ví dụ, nếu tôi loại bỏ "HosteBy" từ lớp này .....Khuôn khổ đối tượng Mã đầu tiên: Cách cập nhật cơ sở dữ liệu theo cách thủ công?

public class Dinner 
{ 
    public int DinnerID { get; set; } 
    public string Title { get; set; } 
    public DateTime EventDate { get; set; } 
    public string Address { get; set; } 
    public string HostedBy { get; set; } 

    public virtual ICollection<RSVP> RSVPs { get; set; } 
} 

... nó ném ngoại lệ này:

Mô hình sao bối cảnh 'NerdDinners' đã thay đổi kể từ khi cơ sở dữ liệu đã được tạo. Hoặc là tự xóa/cập nhật cơ sở dữ liệu, hoặc gọi Database.SetInitializer với một cá thể IDatabaseInitializer. Ví dụ, chiến lược DropCreateDatabaseIfModelChanges sẽ tự động xóa và tạo lại cơ sở dữ liệu, và tùy chọn tạo hạt giống với dữ liệu mới.

Lỗi này vẫn còn ngay cả sau khi loại bỏ trường "HosteBy" theo cách thủ công khỏi cơ sở dữ liệu. Tôi đang thiếu gì ở đây? Tôi có phải xóa/cắt bớt db hoặc có giải pháp khác không?

Trả lời

25

Trong kịch bản đầu tiên mà bạn đã thay đổi Bộ Luật Đầu Model, trước khi bạn đi và sửa đổi cơ sở dữ liệu bằng tay, câu trả lời là để mở (NuGet) Package Manager Console và loại:

update-database -verbose 

Trừ - bởi vì trong này trường hợp bạn đang loại bỏ một cột này sẽ báo cáo rằng nó sắp xóa một cái gì đó, và nó sẽ không xóa bất cứ điều gì mà không có bạn nói rõ ràng là OK.Vì vậy, bạn nhập:

update-database -f -verbose 

Bây giờ điều này sẽ xóa cột bạn có trong Mô hình của mình. -verbose nói để hiển thị cho bạn SQL mà nó chạy. Nếu bạn sợ hãi của chỉ để cho nó xóa mọi thứ và thay vì kiểm tra việc SQL trước khi nó chạy, sử dụng:

cập nhật cơ sở dữ liệu -f -script

Đó thay vào đó sẽ đổ SQL ra một kịch bản bạn có thể nhìn và tự chạy theo cách thủ công.

Trong trường hợp bạn tiếp tục và xóa cột trong cơ sở dữ liệu theo cách thủ công, giờ đây bạn có một kịch bản phức tạp hơn trên tay; bảng EdmMetadata được mô tả trong câu trả lời khác ở đây chứa một hàm băm của toàn bộ cơ sở dữ liệu mà bây giờ không khớp với cơ sở dữ liệu. Bạn có thể chạy SQL thủ công để trả về DB theo cách mà Entity Framework mong đợi (cách nó trước khi bạn sửa đổi nó theo cách thủ công, nó sẽ đưa nó trở lại phù hợp với hàm băm) bằng cách kiểm tra những gì bạn có trước đây và db của bạn trông như thế nào.

Nếu điều đó không khả thi bạn hiện đang ở phần xấu nhất của Mã khung thực thể trước tiên. Bạn cần phải loại bỏ bảng băm và đảo ngược thiết kế db thành các tệp mã.

Tên bảng băm phụ thuộc vào phiên bản của EF. Trong EF4 cũ như bạn đã hỏi, nó được gọi là EdmMetadata. Trong EF5 mới hơn, nó được gọi là __MigrationHistory (trong System Tables trong cơ sở dữ liệu của bạn nếu bạn đang tìm trong SQL Server Management Studio). Bạn sẽ cần xóa nó đi.

Tin tốt ở bước thứ hai, đảo ngược kỹ thuật thành mã, là Microsoft đã phát hành một công cụ vào phiên bản beta sẽ thực hiện việc này cho bạn.

Walk-through of reverse-engineering a db, and EF Power Tools

Bạn có thể bỏ qua nhiều bước đầu có kể từ khi họ chỉ cần thiết lập một DB và thêm một số vô nghĩa với nó để họ có thể chứng minh những gì bạn cần làm: Reverse Engineer một db.

Cập nhật:

Cũng có thể sử dụng Di chuyển thủ công để giải quyết tình huống này. Tạo bản sao lưu của db, sau đó chạy:

add-migration WhateverYouWantToCallThis 

Sửa đổi đối với db EF Việc di chuyển cần chạy sẽ xuất hiện trong lệnh C# được tạo. Bây giờ, bạn có thể tinker với họ để làm việc xung quanh các vấn đề với những gì nó đang cố gắng thực hiện (ví dụ như cố gắng xóa các cột đã bị xóa) và đưa vào những thứ cần thiết để chuyển tiếp (ví dụ: thêm lại một bảng bạn vẫn có trong mô hình của mình nhưng bạn đã xóa bằng tay trong db của mình).

Khi bạn đã thêm điều này và chạy update-database -f, EF Code Trước tiên, bạn sẽ chấp nhận niềm tin rằng bạn đã cập nhật cơ sở dữ liệu theo cách cần và cập nhật giá trị băm dựa trên kết quả cuối cùng. Nếu bạn đã thực hiện các thay đổi đúng, giờ đây bạn có thể tiếp tục với Di chuyển như bình thường. Nếu điều này vẫn gây ra lỗi, bạn thường có thể sao chép các lệnh di chuyển thủ công ra một nơi nào đó và xóa nó, Khôi phục db từ bản sao lưu của bạn, thêm lại di chuyển thủ công và thử lại. Trường hợp xấu nhất bạn sử dụng bước kỹ thuật đảo ngược ở trên.

2

Nếu cơ sở dữ liệu của bạn chứa một số bảng lạ với tên EdmMetadata ngữ cảnh của bạn sử dụng một số cấp độ cơ bản của phiên bản cơ sở dữ liệu. Khi nó tạo ra cơ sở dữ liệu, nó lưu trữ một băm của mô hình của bạn vào bảng này và mỗi lần nó xây dựng một mô hình cho ứng dụng của bạn (lần đầu tiên bạn sử dụng ngữ cảnh sau khi khởi động lại ứng dụng của bạn) nó lại tính toán băm và so sánh nó với băm được lưu trữ trong cái bàn kia. Điều đó có nghĩa là bất kỳ thay đổi nào trong mô hình của bạn sẽ dẫn đến một băm khác và EF sẽ phản ứng với ngoại lệ bạn thấy. Thay đổi thủ công trong cơ sở dữ liệu sẽ không giúp bạn vì bảng chứa vẫn cũ.

Các giải pháp bao gồm:

  • Loại bỏ phiên bản này. Yêu cầu xóa IncludeMetadataConvention như được mô tả here.
  • Cập nhật băm. Nó sẽ yêu cầu thiết kế lại thuật toán cho tính toán băm (ví dụ: Red Gate .NET Reflector, JetBrains dotPeek, SharpDevelop ILSpy hoặc Telerik JustDecompile) và tính toán băm mới từ mô hình biên dịch (hoặc sử dụng phản chiếu để đọc nội bộ từ DbCompiledModel.ModelHash với tính toán băm) mà bạn sẽ lưu trữ trong bảng EdmMetadata.
  • tay xóa cơ sở dữ liệu và để EF tạo một hình mới - bạn sẽ mất tất cả dữ liệu
  • Setting initializer để DropCreateDatabaseIfModelChanges - nó sẽ tự động xóa các cơ sở dữ liệu và tạo ra một cái mới nếu bạn thay đổi mô hình - bạn sẽ mất tất cả dữ liệu
3
+1

Hoặc bước 7 trong hướng dẫn này ;-) http://weblogs.asp.net/scottgu/archive/2011/01/11/vs-2010-sp1-and-sql -ce.aspx Giải pháp thực sự khá đơn giản: Sau khi bạn đã cập nhật cơ sở dữ liệu (loại bỏ/thêm các trường cần thiết theo cách thủ công), bạn phải cắt bớt bảng được tạo tự động "EdmMetadata" vì nó lưu trữ một ModelHash trong đó. Đó là. – Mike

0

Check-out phần của bài viết này trên Mã Đầu tiên Migrations với một cơ sở dữ liệu hiện tại
http://msdn.microsoft.com/en-us/data/dn579398

Đôi khi dự án của bạn và cơ sở dữ liệu của bạn có thể thoát ra khỏi đồng bộ. Vì vậy, bạn có thể phải resynch lược đồ của bạn dựa trên cơ sở dữ liệu hiện có của bạn.



1) Để tạo một sự chuyển đổi dựa trên giản đồ hiện có:
Add-Migration InitialCreate

2) Khởi động Update-Cơ sở dữ liệu sau đó để thêm các mục vào bảng _MigrationsHistory để chỉ rằng quá trình di chuyển hoàn tất đến lược đồ hiện có.

0

Ba điều đơn giản bạn cần phải nhớ khi làm việc trên Mã Đầu tiên

  1. Enable-Migrations
  2. Add-Migration
  3. Cập nhật cơ sở dữ liệu-

Mọi thứ đều tự giải thích.

Bạn cần chạy các lệnh này trên Bảng điều khiển trình quản lý gói theo cách thủ công. Tôi trễ nhưng hy vọng nó sẽ giúp

Các vấn đề liên quan