2011-11-21 17 views
14

Mã khung thực thể Đầu tiên có thể tạo DB cho các POCO sau đây.Mã khuôn khổ thực thể đầu tiên: Ràng buộc KEY NGOẠI HỐI có thể gây ra các chu kỳ hoặc nhiều đường dẫn xếp tầng

public class Item { 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class ItemPair { 
    public int Id { get; set; } 

    public virtual Item FirstItem { get; set; } 
    public virtual Item SecondItem { get; set; } 
} 

Tôi muốn thiết lập mối quan hệ với mục Thứ nhất và Thứ hai thông qua các trường ID chứ không phải toàn bộ lớp "Mục". Vì vậy:

public class ItemPair { 
    public int Id { get; set; } 

    public virtual Item FirstItem { get; set; } 
    public int FirstItem_Id { get; set; } 

    public virtual Item SecondItem { get; set; } 
    public int SecondItem_Id { get; set; } 
} 

cũng hoạt động. Chỉnh sửa: Điều này không thực sự hiệu quả. Chỉ cần tạo thêm cột FirstItem_Id1 và SecontItem_Id2.

Nhưng chỉ cần thay đổi các thuộc tính chính nước ngoài để FirstItemId, SecondItemId, (không có gạch dưới) như vậy:

public class ItemPair { 
    public int Id { get; set; } 

    public virtual Item FirstItem { get; set; } 
    public int FirstItemId { get; set; } 

    public virtual Item SecondItem { get; set; } 
    public int SecondItemId { get; set; } 
} 

kết quả trong ngoại lệ sau đây.

{"Introducing FOREIGN KEY constraint 'ItemPair_SecondItem' on table 'ItemPair' may cause 
cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, 
or modify other FOREIGN KEY constraints.\r\nCould not create constraint. 
See previous errors."} 

Tại sao? Và tôi có thể làm gì để tránh ngoại lệ này.

+0

Phương án này đã giúp tôi tốt hơn http://stackoverflow.com/questions/19373310/introducing-foreign-key-constraint-may-cause-cycles-or-multiple-cascade-paths – Mzn

Trả lời

17

Kỳ vọng của tôi là trong trường hợp đầu tiên thuộc tính Id không được sử dụng trong cơ sở dữ liệu vì FK và EF sẽ tạo hai cột khác (bạn có thể xác thực điều này bằng cách buộc ghép nối thuộc tính điều hướng với thuộc tính FK sử dụng ForeignKeyAttribute). Trong trường hợp thứ hai EF sẽ nhận ra chính xác các thuộc tính của bạn nhưng nó cũng sẽ sử dụng quy ước xóa tầng sẽ gây ra lỗi trong máy chủ SQL. Bạn có hai thuộc tính từ bảng trỏ đến cùng một bậc cha mẹ. Trên thực tế trong cơ sở dữ liệu bạn có thể tạo ItemPair từ cùng một Item (cả hai FK được đặt thành cùng một Id). Nếu cả hai quan hệ đều có phép xóa tầng, nó sẽ dẫn đến nhiều đường dẫn tầng => không được phép trong máy chủ SQL.

Giải pháp ở đây là lập bản đồ thành thạo để xác định cách các mối quan hệ được ánh xạ theo cách thủ công. Here là ví dụ.

+0

Cảm ơn bạn rất nhiều vì điều này. Đã dành một vài giờ cố gắng tìm ra. Nó không xảy ra với tôi để đọc lên trên quy ước xóa thác. – Pauly

21

Tôi quyết định chỉ xóa quy ước xóa tầng.

protected override void OnModelCreating(DbModelBuilder modelBuilder) { 
     base.OnModelCreating(modelBuilder); 

     modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>(); 
     modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); 

    } 

Lý do là:

  • tôi thích để đánh dấu kỷ lục bị xóa hoặc ngừng hoạt động vì mục đích kiểm toán.
  • Tối đa, tôi chỉ xóa các bảng giao diện/ánh xạ.
  • Với một ORM Nó là tương đối nhỏ để lặp qua và xóa các bản ghi con trong trường hợp hiếm hoi mà tôi cần.

Cảm ơn Ladislav Mrnka đã chỉ cho tôi đúng hướng.

+0

Cảm ơn Chúa, tôi đã đọc một câu trả lời khác cho một câu hỏi tương tự và tôi nghĩ rằng tôi sẽ cần phải làm tất cả các bản đồ dựa trên thuộc tính của tôi thành thạo. IMHO, EF cố gắng làm quá nhiều theo mặc định. – Josh

+0

Tôi cũng cảm thấy như vậy, và vì vậy tôi bắt đầu với ánh xạ dựa trên thuộc tính. Tuy nhiên, bây giờ tôi sử dụng ánh xạ API Fluent vì nó dường như cho tôi nhiều quyền kiểm soát hơn cũng như giữ cho POCO không bị trôi dạt.Hãy thử cài đặt "Entity Framework Power Tools" và đảo ngược kỹ thuật cơ sở dữ liệu hiện tại của bạn. Tôi nghĩ rằng một khi bạn nhìn thấy ánh xạ nó tạo ra, nó sẽ không cảm thấy xa lạ như vậy. – Pauly

+0

Điều này có vẻ tuyệt vời! Nhưng tiếc là đã không làm việc trong trường hợp của tôi. Những gì tôi không nhận được là làm thế nào tôi có thể gọi WillCascadeOnDelete (false) trên mỗi mối quan hệ duy nhất, và loại bỏ quy ước này, và vẫn còn trong kịch bản SQL của tôi (verbose danh sách) Tôi có thể thấy nó tạo ra các ràng buộc vi phạm. Tại của lệnh này là "ON DELETE CASCADE", mặc dù tất cả công việc của tôi trong ánh xạ trôi chảy để loại bỏ hành vi này. –

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