7

Tôi có một lớp Nội dung có thể có một parentId để kế thừa nhưng tôi cũng muốn nó có danh sách nội dung con không có gì để làm với cây thừa kế này.Mã khuôn khổ thực thể Lớp đầu tiên với cha mẹ và con cùng loại với lớp riêng của nó

Về cơ bản tôi muốn có một bảng liên kết là ChildContentRelationship với Id cho parentContent và childContent trong đó và lớp Content sẽ có danh sách ChildContentRelationship.

Điều này đã gây ra rất nhiều lỗi.

Dưới đây là WAHT tôi loại muốn làm

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

    public int? ParentContentId { get; set; } 
    public virtual Content ParentContent { get; set; } 

    public string Name { get; set; } 

    public int ContentTypeId { get; set; } 
    public virtual ContentType ContentType { get; set; } 

    public virtual ICollection<Property> Properties { get; set; } 

    public virtual ICollection<ChildContentRelationship> ChildContent { get; set; } 
} 

Làm thế nào tôi sẽ thiết lập này trong EF?

+0

Bạn đang sử dụng phiên bản Khuôn khổ thực thể nào và loại phương pháp nào (đầu tiên là db, kiểu đầu tiên, mã đầu tiên)? Và tại sao bạn muốn một bảng liên kết? Bạn không có mối quan hệ một-nhiều, * một * cha mẹ và * nhiều * trẻ em? – Slauma

+0

EF 4.1 +, Mã trước. Đó là vì ParentContentId này. Xem Tôi muốn Nội dung có thể có một phụ huynh kế thừa bất kỳ thuộc tính nào từ lược đồ loại nội dung của phụ huynh. Nhưng tôi cũng muốn một phần nội dung có tham chiếu đến nội dung khác không có trong phân cấp cây này.Điều này là để tôi có thể hiển thị nội dung con, giống như điều khiển. Tôi có thể đặt tên nó như là điều khiển và có một điều khiển có một ContentId tôi giả sử? –

+0

"Mã đầu tiên" đã có trong tiêu đề, ngu ngốc của tôi, tôi đã không nhận thấy rằng, xin lỗi. – Slauma

Trả lời

18

Tôi không chắc liệu tôi có hiểu chính xác mô hình của bạn hay không. Hãy thảo luận về các tùy chọn.

Trong giây lát, tôi bỏ qua thực thể bổ sung này ChildContentRelationship và tôi giả định bộ sưu tập ChildContent là loại ICollection<Content>.

  • Lựa chọn 1:

    tôi cho rằng ParentContentsở hữu nghịch đảo của ChildContent. Điều đó có nghĩa là nếu bạn có Content với Id = x và Nội dung này có ChildContent với Id = y thì ChildContents ParentContentId phải luôn là x. Đây chỉ là một liên kết duy nhất và ParentContentChildContent là các điểm cuối của cùng một liên kết này.

    Các bản đồ cho mối quan hệ này có thể được tạo ra hoặc với các chú thích dữ liệu ...

    [InverseProperty("ParentContent")] 
    public virtual ICollection<Content> ChildContent { get; set; } 
    

    ... hoặc với API thạo:

    modelBuilder.Entity<Content>() 
        .HasOptional(c => c.ParentContent) 
        .WithMany(c => c.ChildContent) 
        .HasForeignKey(c => c.ParentContentId); 
    

    Tôi nghĩ rằng đây không phải là những gì bạn muốn ("... không liên quan gì đến ..."). Tuy nhiên, hãy xem xét đổi tên thuộc tính điều hướng của bạn. Nếu ai đó đọc Parent...Child... anh ấy rất có khả năng sẽ giả sử họ tạo một cặp thuộc tính điều hướng cho cùng một mối quan hệ.

  • Phương án 2:

    ParentContent không phải là thuộc tính nghịch đảo của ChildContent đó có nghĩa là bạn thực sự có hai mối quan hệ độc lập và các thiết bị đầu cuối thứ hai của cả hai mối quan hệ không được tiếp xúc trong lớp mô hình của bạn.

    Các bản đồ cho ParentContent sẽ trông như thế này:

    modelBuilder.Entity<Content>() 
        .HasOptional(c => c.ParentContent) 
        .WithMany() 
        .HasForeignKey(c => c.ParentContentId); 
    

    WithMany() không có tham số chỉ ra rằng thiết bị đầu cuối thứ hai không phải là một tài sản trong lớp mô hình của bạn, đặc biệt nó là khôngChildContent.

    Bây giờ, câu hỏi vẫn còn: Loại mối quan hệ nào ChildContent thuộc về?Nó là một-nhiều hay là một mối quan hệ nhiều-nhiều?

    • Lựa chọn 2a

      Nếu một Content đề cập đến ChildContent s khác và không thể có một giây Content đó sẽ tham khảo với cùng ChildContent s (con cái của một Contentđộc đáo, vì vậy để nói) thì bạn có mối quan hệ một-nhiều. (Điều này cũng tương tự như mối quan hệ giữa đơn đặt hàng và trật tự các mặt hàng: Một item để chỉ có thể thuộc về một trật tự nhất định.)

      Các bản đồ cho ChildContent sẽ trông như thế này:

      modelBuilder.Entity<Content>() 
          .HasMany(c => c.ChildContent) 
          .WithOptional(); // or WithRequired() 
      

      Bạn sẽ có một cột khóa ngoài bổ sung trong bảng Content trong cơ sở dữ liệu của bạn thuộc về liên kết này nhưng không có thuộc tính FK tương ứng trong lớp thực thể.

    • Lựa chọn 2b

      Nếu nhiều Content s có thể tham khảo với cùng ChildContent s sau đó bạn có một mối quan hệ nhiều-nhiều. (Điều này cũng tương tự như mối quan hệ giữa người sử dụng và vai trò: Có thể có nhiều người sử dụng trong vai trò tương tự và người dùng có thể có nhiều vai trò.)

      Các bản đồ cho ChildContent sẽ trông như thế này:

      modelBuilder.Entity<Content>() 
          .HasMany(c => c.ChildContent) 
          .WithMany() 
          .Map(x => 
          { 
           x.MapLeftKey("ParentId"); 
           x.MapRightKey("ChildId"); 
           x.ToTable("ChildContentRelationships"); 
          }); 
      

      Ánh xạ này sẽ tạo một bảng tham gia ChildContentRelationships trong cơ sở dữ liệu nhưng bạn không cần một thực thể tương ứng cho bảng này.

    • Lựa chọn 2c

      Chỉ trong trường hợp đó, mối quan hệ nhiều-nhiều có tính chất hơn ngoài hai phím (ParentIdChildId) (ví dụ một cái gì đó giống như CreationDate hoặc RelationshipType hoặc ...) bạn sẽ phải đưa ra một thực thể mới ChildContentRelationship vào mô hình của bạn:

      public class ChildContentRelationship 
      { 
          [Key, Column(Order = 0)] 
          public int ParentId { get; set; } 
          [Key, Column(Order = 1)] 
          public int ChildId { get; set; } 
      
          public Content Parent { get; set; } 
          public Content Child { get; set; } 
      
          public DateTime CreationDate { get; set; } 
          public string RelationshipType { get; set; } 
      } 
      

      Bây giờ lớp Content của bạn sẽ có một bộ sưu tập của ChildContentRelationship s:

      public virtual ICollection<ChildContentRelationship> ChildContent 
          { get; set; } 
      

      Và bạn có hai một-nhiều mối quan hệ:

      modelBuilder.Entity<ChildContentRelationship>() 
          .HasRequired(ccr => ccr.Parent) 
          .WithMany(c => c.ChildContent) 
          .HasForeignKey(ccr => ccr.ParentId); 
      
      modelBuilder.Entity<ChildContentRelationship>() 
          .HasRequired(ccr => ccr.Child) 
          .WithMany() 
          .HasForeignKey(ccr => ccr.ChildId); 
      

Tôi tin rằng bạn muốn một trong hai tùy chọn 2a hay 2b, nhưng tôi không chắc chắn.

+2

Cảm ơn bạn đã xóa nội dung đó, tôi cho rằng tôi đang tìm tùy chọn 2b, có thể yêu cầu đặt tên đã bị xóa. Tôi nghĩ rằng đó là một điều khiển thực tế hơn và vì vậy có thể cần một lớp/thiết kế khác. Tôi sẽ thử vào ngày mai. –

+1

Đây là câu trả lời! :) –

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