29

Tôi mới dùng mã EF5 Đầu tiên và tôi đang làm việc với một chứng minh-khái niệm trước khi bắt tay vào một dự án tại nơi làm việc.Mã EF5 Đầu tiên - Thay đổi Loại Cột Với ​​Di chuyển

Tôi đã bước đầu tạo ra một mô hình trông giống như

public class Person { 
    public int Id { get; set; } 
    public string FirstName { get; set;} 
    public string Surname {get;set;} 
    public string Location {get;set;} 
} 

Và tôi đã thêm một vài hồ sơ sử dụng một ứng dụng MVC chút tôi bị mắc kẹt trên đỉnh.

Bây giờ tôi muốn thay đổi cột Location một enum, một cái gì đó như:

public class Person { 
    public int Id { get; set; } 
    public string FirstName { get; set;} 
    public string Surname {get;set;} 
    public Locations Location {get;set;} 
} 

public enum Locations { 
    London = 1, 
    Edinburgh = 2, 
    Cardiff = 3 
} 

Khi tôi thêm sự di cư mới tôi nhận được:

AlterColumn("dbo.People", "Location", c => c.Int(nullable: false)); 

nhưng khi tôi chạy cập nhật cơ sở dữ liệu tôi gặp lỗi

Conversion failed when converting the nvarchar value 'London' to data type int. 

Có cách nào trong quá trình di chuyển cắt bảng trước khi chạy câu lệnh thay đổi hay không ?

Tôi biết tôi có thể mở cơ sở dữ liệu và làm theo cách thủ công, nhưng có cách nào thông minh hơn không?

+2

tôi muốn đề nghị các nhà phát triển ở các vị trí tương tự mà họ thấy nếu chuyển đổi được xử lý tự động bởi Entity Framework trước khi làm theo một số các câu trả lời trên trang này. Ví dụ, tôi thấy nó xử lý chuyển đổi giữa một chuỗi và một số thập phân và ngược lại một lần nữa mà không có sự trợ giúp nào từ tôi - sự di chuyển mà Add-Migration được tạo ra hoạt động tốt. Rõ ràng, hãy thử nó trên một cơ sở dữ liệu địa phương/thử nghiệm trước khi áp dụng nó vào sản xuất! – pipedreambomb

Trả lời

45

Cách thông minh nhất có lẽ là không thay đổi loại. Nếu bạn cần phải làm điều này, tôi muốn đề nghị bạn làm theo các bước sau:

  1. Thêm một cột mới với kiểu mới của bạn
  2. Sử dụng Sql() để tiếp nhận các dữ liệu từ cột gốc sử dụng một báo cáo cập nhật
  3. Tháo cột cũ
  4. Đổi tên cột mới

này đều có thể được thực hiện trong sự di cư cùng, kịch bản SQL đúng sẽ được tạo ra. Bạn có thể bỏ qua bước 2 nếu bạn muốn loại bỏ dữ liệu của mình. Nếu bạn muốn tiếp quản nó, hãy thêm câu lệnh thích hợp (cũng có thể chứa một câu lệnh chuyển đổi).

Thật không may Code First Migrations không cung cấp các cách dễ dàng hơn để thực hiện việc này.

Đây là đoạn mã ví dụ:

AddColumn("dbo.People", "LocationTmp", c => c.Int(nullable: false)); 
Sql(@" 
    UPDATE dbp.People 
    SET LocationTmp = 
     CASE Location 
      WHEN 'London' THEN 1 
      WHEN 'Edinburgh' THEN 2 
      WHEN 'Cardiff' THEN 3 
      ELSE 0 
     END 
    "); 
DropColumn("dbo.People", "Location"); 
RenameColumn("dbo.People", "LocationTmp", "Location"); 
+0

Lưu ý nhanh: sử dụng cột tạm thời là cách duy nhất tôi tìm thấy để thực hiện việc này khi di chuyển 'Xuống()'.Các cập nhật lược đồ dường như đang chạy bên trong một giao dịch cũng chứa lệnh 'Sql()', như một cập nhật cột từ các giá trị 'Integer' trở lại thành' Chuỗi' thất bại với cùng thông báo lỗi — lần này trên 'Sql() 'thay vì' AlterColumn() '. Điều này mặc dù chúng ta chạy 'Sql()' SAU 'AlterColumn() '. – InteXX

12

Dựa trên câu trả lời @ JustAnotherUserYouMayKnow, nhưng dễ dàng hơn.

Cố gắng đầu tiên thực hiện Sql() lệnh và sau đó AlterColumn():

Sql(@" 
    UPDATE dbo.People 
    SET Location = 
     CASE Location 
      WHEN 'London' THEN 1 
      WHEN 'Edinburgh' THEN 2 
      WHEN 'Cardiff' THEN 3 
      ELSE 0 
     END 
    "); 
AlterColumn("dbo.People", "Location", c => c.Int(nullable: false)); 
+1

Tôi thích nó hơn câu trả lời được đánh dấu: Nó không cần một cột tạm thời. – Marcel