2010-03-12 23 views
13

tôi đọc this article nơi Ayende nói NHibernate thể (so với EF 4):Paging qua một bộ sưu tập lười biếng-nạp với NHibernate

  • Collection với lười biếng =”thêm” - Lazy thêm có nghĩa là NHibernate thích nghi với các hoạt động mà bạn có thể chạy trên đầu bộ sưu tập của mình. Điều đó có nghĩa là blog đó.Posts.Count sẽ không bắt buộc tải toàn bộ bộ sưu tập, nhưng thay vào đó sẽ tạo một "số đếm (*) từ Bài đăng có tuyên bố BlogId = 1" và rằng blog.Posts. Chứa() sẽ tương tự như vậy dẫn đến một truy vấn thay vì trả giá tải toàn bộ bộ sưu tập vào bộ nhớ.
  • Bộ sưu tập các bộ lọc và các bộ sưu tập paged - điều này cho phép bạn xác định bộ lọc bổ sung (bao gồm phân trang!) Trên đầu trang của các đơn vị của bạn bộ sưu tập, có nghĩa là bạn có thể dễ dàng trang thông qua blog.Posts bộ sưu tập, và không có để tải toàn bộ nội dung vào bộ nhớ .

Vì vậy, tôi quyết định đặt cùng một trường hợp thử nghiệm. Tôi tạo ra các mô hình cliché Blog như một cuộc biểu tình đơn giản, với hai lớp như sau:

public class Blog 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Name { get; set; } 

    public virtual ICollection<Post> Posts { get; private set; } 

    public virtual void AddPost(Post item) 
    { 
     if (Posts == null) Posts = new List<Post>(); 
     if (!Posts.Contains(item)) Posts.Add(item); 
    } 
} 

public class Post 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Title { get; set; } 
    public virtual string Body { get; set; } 
    public virtual Blog Blog { get; private set; } 
} 

file ánh xạ của tôi trông như thế này:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="Model.Blog, TestEntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Blogs"> 
    <id name="Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Id" /> 
     <generator class="identity" /> 
    </id> 
    <property name="Name" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Name" /> 
    </property> 
    <property name="Type" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Type" /> 
    </property> 
    <bag lazy="extra" name="Posts"> 
     <key> 
     <column name="Blog_Id" /> 
     </key> 
     <one-to-many class="Model.Post, TestEntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </bag> 
    </class> 
</hibernate-mapping> 

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="property" auto-import="true" default-cascade="none" default-lazy="true"> 
    <class xmlns="urn:nhibernate-mapping-2.2" name="Model.Post, TestEntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="Posts"> 
    <id name="Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Id" /> 
     <generator class="identity" /> 
    </id> 
    <property name="Title" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Title" /> 
    </property> 
    <property name="Body" type="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"> 
     <column name="Body" /> 
    </property> 
    <many-to-one class="Model.Blog, TestEntityFramework, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Blog"> 
     <column name="Blog_id" /> 
    </many-to-one> 
    </class> 
</hibernate-mapping> 

trường hợp thử nghiệm của tôi trông giống như sau:

 using (ISession session = Configuration.Current.CreateSession()) // this class returns a custom ISession that represents either EF4 or NHibernate 
     { 
      blogs = (from b in session.Linq<Blog>() 
         where b.Name.Contains("Test") 
         orderby b.Id 
         select b); 

      Console.WriteLine("# of Blogs containing 'Test': {0}", blogs.Count()); 
      Console.WriteLine("Viewing the first 5 matching Blogs."); 

      foreach (Blog b in blogs.Skip(0).Take(5)) 
      { 
       Console.WriteLine("Blog #{0} \"{1}\" has {2} Posts.", b.Id, b.Name, b.Posts.Count); 
       Console.WriteLine("Viewing first 5 matching Posts."); 

       foreach (Post p in b.Posts.Skip(0).Take(5)) 
       { 
        Console.WriteLine("Post #{0} \"{1}\" \"{2}\"", p.Id, p.Title, p.Body); 
       } 
      } 
     } 

Sử dụng lazy = "extra", cuộc gọi tới b.Posts.Count không thực hiện một SELECT COUNT(Id)... thật tuyệt. Tuy nhiên, b.Posts.Skip(0).Take(5) chỉ cần lấy tất cả các bài viết cho Blog.Id =? Id, và sau đó LINQ ở phía ứng dụng chỉ là lấy 5 đầu tiên từ bộ sưu tập kết quả.

Điều gì mang lại?

+1

+1 cho một câu hỏi hay. Tôi đã tự hỏi về khả năng tải lười biếng NHibernates trong một thời gian nhưng không có thời gian để thử chúng. –

+1

có thể phần LINQ to NHibernate liên quan đến bộ lọc thu thập không được thực hiện – Jaguar

+0

Chỉ cần một báo trước cho việc sử dụng lazy = "extra". Chúng tôi bắt đầu sử dụng điều này trên ứng dụng của chúng tôi và tất cả mọi thứ làm việc tốt cho đến khi chúng tôi triển khai đến một máy Sql Server 2000 (vẫn là phần mềm được chấp thuận của khách hàng). Vì chúng tôi sử dụng một guid làm trường nhận dạng của mình, chúng tôi bắt đầu nhận ngoại lệ, 'Không thể thực hiện đếm trên số nhận dạng duy nhất' (xấp xỉ). Tôi nhìn vào mã nguồn NH và tìm thấy nó là tải phụ thêm mà chọn cột khóa đầu tiên và không 'chọn đếm ()', đó là lĩnh vực GUID của chúng tôi. –

Trả lời

9

Tôi khá chắc chắn (đọc các nhận xét) mà anh ấy đang nói về Trình tạo của ISession.

Bạn có thể làm phân trang như thế này (từ các tài liệu 13.13):

Collections are pageable by using the IQuery interface with a filter: 

IQuery q = s.CreateFilter(collection, ""); // the trivial filter 
q.setMaxResults(PageSize); 
q.setFirstResult(PageSize * pageNumber); 
IList page = q.List(); 

Hoặc (từ các tài liệu 17.1.4):

s.CreateFilter(lazyCollection, "").SetFirstResult(0).SetMaxResults(10).List(); 

Đó là không phải là một cách mượt mà bằng cách sử dụng hệ thống Phương thức .Linq. Tôi đoán họ sẽ tham gia cú pháp một thời gian.

+0

đó là những gì tôi làm và nó hoạt động như quảng cáo – Jaguar

+1

Hmm, vâng. đáng thất vọng. Nhưng, điều đó sẽ làm. Cảm ơn. – HackedByChinese

+0

Xin chào, Bạn có thể đăng ví dụ ban đầu với kỹ thuật này được triển khai không? Cảm ơn. – UpTheCreek

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