2009-08-03 57 views
7

Tôi có một mối quan hệ một-nhiều đệ quy có giá trị lười mặc định là true. Tôi có thể viết mã nào với API NH để truy xuất hiệu quả cây ENTIRE AS NẾU tôi đã lười biếng = "sai" trên ánh xạ SubCategories?Vui lòng tải mối quan hệ đệ quy

Đây là đệ quy một-nhiều mối quan hệ:

<class name="Category" lazy="false"> 
    ... 
    <list name="SubCategories" fetch="subselect"> 
      <key column="ParentCategoryID"/> 
      <index column="PositionInList"/> 
      <one-to-many class="Category"/> 
    </list> 

tôi không chỉ định lười biếng = "false" trong danh sách kể từ sự lười biếng là cần thiết trong khoảng một nửa các truy vấn tôi cần phải chạy. Tôi có fetch = "subselect" trên danh sách như là một tối ưu hóa khi tôi quản lý để lấy toàn bộ cây.

Tôi đã thử API ICriteria:

session.CreateCriteria<Category>().SetFetchMode("SubCategories", FetchMode.Eager).Add(Restrictions.IsNull("ParentCategory")).SetResultTransformer(CriteriaSpecification.DistinctRootEntity).List<Category>(); 

nhưng điều đó chỉ hăm hở nạp chỉ cấp độ đầu tiên trong hệ thống phân cấp.

Trả lời

8

Xem Ayende của trang web: Efficiently Selecting a Tree. Tôi đã sử dụng thành công kỹ thuật này trong các ứng dụng của riêng tôi. Với ICriteria, có vẻ như sau:

session.CreateCriteria<Category>() 
    .SetFetchMode("SubCategories", FetchMode.Join) 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Category>() 
    .Where(x => x.ParentCategory == null); 

Sự khác biệt chính giữa phiên bản này và những gì bạn đã thử là cách áp dụng bộ lọc "ParentCategory == null". Nó phải được bỏ ra khỏi truy vấn được gửi đến cơ sở dữ liệu để lấy toàn bộ cây - nhưng chúng ta vẫn cần truy vấn để chỉ trả về các nút gốc của cây, vì vậy chúng ta sẽ sử dụng LINQ để tìm những cái sau truy vấn cơ sở dữ liệu đã hoàn thành.

0

Không chắc chắn nếu nó giúp nhưng hãy xem tại địa chỉ: map a tree in NHibernate

+0

Vâng, đó là một bài viết hữu ích và tôi đã đọc nó. Khi tôi đang điều tra việc tải nhanh cây cách đây vài tháng, tôi thấy phần "Eager load ancestors and descendants" có liên quan. Cơ sở dữ liệu của tôi là SQL Compact, tuy nhiên, và không hỗ trợ CTE (truy vấn phân cấp). Vì vậy, viết một truy vấn duy nhất giải quyết vấn đề có vẻ không thể. – HappyNomad

1

Tôi đã sử dụng mã của Daniel làm cơ sở để giải quyết vấn đề. Tôi cũng đã thử nghiệm với HQL tương đương mà tôi đã chia sẻ bên dưới. HQL thực hiện nhanh hơn một chút, nhưng tôi đã đi với ICriteria vì tôi có thể chọn giữa FetchModel.Join và FetchModel.Lazy.

session.CreateQuery("from Category as c left join fetch c.SubCategories") 
    .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
    .List<Category>() 
    .Where(c => c.ParentCategory == null); 
Các vấn đề liên quan