2009-06-03 37 views
11

Vì vậy, trong một mô hình điển hình, nơi bạn có cha mẹ có thể có nhiều trẻ em và một đứa trẻ chỉ có thể có một phụ huynh, bạn quản lý việc thêm trẻ như thế nào. Tôi đã sử dụng cách tiếp cận này;Thực hành tốt nhất để xử lý các bộ sưu tập cha-con NHibernate

public class Parent 
{ 
    public Parent() 
    { 
     Children = new List<Child>(); 
    } 

    public IList<Child> Children 
    { 
     get; 
     private set; 
    } 
} 

public class Child 
{ 
    public Parent Parent 
    { 
     get; 
     set; 
    } 
} 

var child = new Child(); 
var parent = new Parent(); 
parent.Children.Add(child); 
child.Parent = parent; 

Vấn đề là ở khắp mọi nơi tôi muốn thêm một đứa trẻ mới, tôi phải nhớ thêm tham chiếu cho cả trẻ em và cha mẹ và một chút đau. Tôi chỉ có thể thêm một phương thức AddChild vào lớp cha và làm cho có trách nhiệm thêm trẻ em - vấn đề bây giờ là có 2 cách để thêm một đứa trẻ, thông qua thuộc tính Trẻ em và phương thức. Vậy đây có phải là giải pháp tốt hơn không?

public class Parent 
{ 
    public Parent() 
    { 
     children = new List<Child>(); 
    } 

    private IList<Child> children 
    { 
     get; 
     private set; 
    } 

    public IEnumerable<Child> Children 
    { 
     get 
     { 
      return children; 
     } 
    } 

    public void AddChild(Child child) 
    { 
     children.Add(child); 
     child.Parent = this; 
    } 
} 

Có bất kỳ hướng dẫn nào để thực hành tốt nhất về điều này không và bạn làm gì?

Trả lời

2

tôi làm điều đó như thế ngoại trừ việc tôi không sử dụng tài sản để xem danh sách tin

private IList<Child> _children 
public IEnumerable<Child> Children 
{ 
    get 
    { 
     return children; 
    } 
} 
+2

đây là một giải pháp tốt nhưng với một nhược điểm rằng nếu người tiêu dùng bỏ các trẻ em để IList ông sẽ truy cập vào danh sách và có thể sửa đổi nó .. cách khác có thể được sử dụng ReadOnlyCollection <> –

10

Đây không phải là vấn đề về NHibernate.

Bạn nên triển khai phương thức AddChild. Các lớp học chịu trách nhiệm về tính nhất quán của chúng, vì vậy chúng không nên phơi bày bất kỳ thứ gì không có sẵn. Ví dụ, danh sách Trẻ em (có thể thay đổi) nên được ẩn đi. Việc trưng ra một IEnumerable là một ý tưởng hay.

Mã thứ hai của bạn là điểm khởi đầu tốt. Bạn có thể cần thêm một số phương thức, như RemoveChild hoặc CoundChildren.

+0

Nói ví dụ thứ hai mối quan tâm duy nhất của tôi là cách điều này có thể hoạt động với LINQ to NHibernate. Khi thuộc tính được ánh xạ thực tế giờ là riêng tư, tôi sẽ giả định rằng nó sẽ không hiển thị được. Có suy nghĩ gì không? – Gareth

+0

Bạn có thể chỉ định trong ánh xạ của mình rằng NHibernte nên sử dụng trường thay vì thuộc tính khi đặt giá trị. (Hãy xem thuộc tính truy cập chẳng hạn). –

+0

Vâng, những gì tôi đã nhận được là khi Linq NHibernate được hoàn thành như thế nào bạn có thể sử dụng nó nếu lĩnh vực này là riêng tư và truy cập công cộng chỉ trả về một tham chiếu đến bộ sưu tập ban đầu. Ví dụ. session.Linq () .Where (x => x.Children.Name.Equals ("Jonnie")) – Gareth

5

tôi làm điều đó như thế này:

public class Parent 
{ 
    private ISet<Child> _children = new HashedSet<Child>(); 

    public ReadOnlyCollection<Child> Children 
    { 
     get{ return new List(_children).AsReadOnly(); } 
    } 

    public void AddChild(Child c) 
    { 
     if(c != null && !_children.Contains (d)) 
     { 
      c.Parent = this; 
      _children.Add (c); 
     } 
    } 
} 

Vì vậy, trên thực tế, đó là một chút gì Stefan nói là tốt. Tôi chỉ phơi bày một bản sao chỉ đọc của danh sách Trẻ em, để bạn có thể dễ dàng lặp lại con cái của một phụ huynh, và nhận được số con mà cha mẹ có. Thêm và xóa trẻ em cho phụ huynh, phải được thực hiện bằng phương pháp thành viên RemoveChild & RemoveChild.

+1

Một tập hợp sẽ không thêm bản sao vì vậy không cần kiểm tra xem đứa trẻ đã tồn tại chưa. –

-1

Tôi không thích tất cả các phương thức thêm AddXXX()RemoveXXX() làm lộn xộn giao diện thực thể của mình. Thay vào đó, tôi có một danh sách tùy chỉnh giúp tăng sự kiện khi các phương thức Add()Remove() được gọi.

Các liên kết sau đó xảy ra trong xử lý sự kiện:

public class Course() 
{ 
    public Course() 
    { 
    this.Topics = new EntityList<Topic>(); 
    this.Topics.AddItem += new AddItemEventHandler<Topic>(Topic_AddItem); 
    this.Topics.RemoveItem += new RemoveItemEventHandler<Topic>(Topic_RemoveItem); 
    } 

    public EntityList<Topic> Topics { get; private set; } 

    private void Topic_AddItem(Topic item, object args) 
    { 
    // Replace with your linking code: 
    EntityLinker.Link(this).With(item, args); 
    } 

    private void Topic_RemoveItem(Topic item, object args) 
    { 
    // Replace with your unlinking code: 
    EntityLinker.Unlink(this).From(item, args); 
    } 
} 
+4

Tôi không thích cách tiếp cận này. :) Có nhiều 'ma thuật' xảy ra đằng sau hậu trường. Tôi nhớ rằng Ayende đã từng sử dụng cách tiếp cận này (tốt trong generics NHibernate nếu tôi không nhầm), nhưng bây giờ tôi không thấy anh ta bằng cách sử dụng phương pháp này nữa. Tôi chỉ thấy rằng logic 'liên kết' bị ẩn đi nhiều. Bên cạnh đó, tôi không thấy thêm các phương thức Addxxxx vào các thực thể của tôi khi làm lộn xộn giao diện. Hơn nữa, tôi thấy nó tốt hơn vì nó rõ ràng hơn. –

+0

Điều này có vẻ không dễ đọc đối với tôi. – UpTheCreek

1

Tôi đang sử dụng công IEnumerable với Thêm | Gỡ bỏ phương pháp tiếp cận phương pháp.

Tuy nhiên, tôi không thích lắm vì nó không trực quan và định nghĩa lớp học.

Tôi tự hỏi tại sao mọi người không sử dụng CustomCollection nơi họ ghi đè các chức năng Thêm, Xóa, Thay thế ?? (giống như nó được thực hiện ở khắp mọi nơi trong mã MS) ????

0

Tôi hỗ trợ giải pháp được chấp nhận cho câu hỏi này, tuy nhiên giải pháp được trình bày không hoàn chỉnh, vì việc sử dụng các trường riêng yêu cầu một số cấu hình bổ sung trong các người lập bản đồ. Vì lợi ích của người khác, sau đây là giải pháp hoàn chỉnh:

public partial class Test 
{ 
    private readonly IList<Child> children = new List<Child>(); 
    public virtual IEnumerable<Child> Children 
    { 
     get 
     { 
      return children; 
     } 
    } 
} 

Lưu ý rằng bộ sưu tập công khai phải là ảo để NHibernate sử dụng.Tôi cũng muốn biến nó thành một trường chỉ đọc được khởi tạo khi lớp được tạo ra để đảm bảo nó tồn tại trong mọi tình huống. Đây là trình ánh xạ được liên kết:

public class TestMap : ClassMap<Test> 
{ 
    ... 
    HasMany(s => s.Children).Access.CamelCaseField(); 
} 

Thuộc tính Access cho phép sử dụng trường riêng khi ánh xạ giá trị vào mô hình. Ngoài ra còn có các tùy chọn khác trên thuộc tính Access cho phép sử dụng các cấu hình đặt tên khác nhau.

0

Nếu bạn có khóa ngoài trong DB của mình và bạn đang sử dụng Identity (SQL Server) để tạo khóa chính, bạn sẽ NEED backlink từ con này sang phụ huynh. Khác, chèn sẽ khiếu nại về trẻ em bởi vì nhibernate cần phải làm một số trở lại và ra cho ID cha mẹ, nhưng nó đã không thực hiện nó được nêu ra.

Điều chúng tôi đã làm để loại bỏ các liên kết ngược: Sử dụng trình phát HiLo NHibernate. Bằng cách này, NHibernate luôn có các Id cần để chèn quan hệ cha/con của bạn.

< 3!

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