分页在一个延迟加载集合与NHibernate

分页在一个延迟加载集合与NHibernate

本文介绍了分页在一个延迟加载集合与NHibernate的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我阅读了其中Ayende表示NHibernate可以(与EF 4相比):

所以我决定把一个测试用例放在一起。我创建了cliché博客模型作为一个简单的示范,有两个类如下:

  public class Blog 
{
public virtual int Id {get;私人集}
public virtual string Name {get;组; }

public virtual ICollection< Post>帖子{get;私人集}

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;私人集}
public virtual string Title {get;组; }
public virtual string Body {get;组; }
public virtual Blog Blog {get;私人集}
}

我的映射文件看起来像这样:

 < hibernate-mapping xmlns =urn:nhibernate-mapping-2.2default-access =propertyauto-import =true nonedefault-lazy =true> 
< class xmlns =urn:nhibernate-mapping-2.2name =Model.Blog,TestEntityFramework,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = nulltable =Blogs>
< id name =Idtype =System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089>
< column name =Id/>
< generator class =identity/>
< / id>
< property name =Nametype =System.String,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089>
< column name =Name/>
< / property>
< property name =Typetype =System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089>
< column name =Type/>
< / property>
< bag lazy =extraname =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.2default-access =propertyauto-import =truedefault-cascade =nonedefault-lazy = true>
< class xmlns =urn:nhibernate-mapping-2.2name =Model.Post,TestEntityFramework,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = nulltable =Posts>
< id name =Idtype =System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089>
< column name =Id/>
< generator class =identity/>
< / id>
< property name =Titletype =System.String,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089>
< column name =Title/>
< / property>
< property name =Bodytype =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 = nullname =Blog>
< column name =Blog_id/>
< / many-to-one>
< / class>
< / hibernate-mapping>

我的测试用例看起来像这样:

  using(ISession session = Configuration.Current.CreateSession())//这个类返回一个自定义的ISession,代表EF4或NHibernate 
{
blogs = from b in session.Linq< Blog>()
其中b.Name.Contains(Test)
orderby b.Id
select b);

Console.WriteLine(#of Blogs containing'Test':{0},blogs.Count());
Console.WriteLine(查看前5个匹配的博客。

foreach(博客b在blogs.Skip(0).Take(5))
{
Console.WriteLine(Blog#{0} \{1} \有{2}帖子。,b.Id,b.Name,b.Posts.Count);
Console.WriteLine(查看前5个匹配的帖子。

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

使用 lazy = extra,调用 b.Posts.Count 会执行 SELECT COUNT(Id)... 这是伟大的。但是, b.Posts.Skip(0).Take(5)刚刚抓住Blog.Id =?id的所有帖子,然后LINQ在应用程序端

解决方案
>我很肯定(阅读评论),他说的是ISession的CreateFilter。



您可以这样(从文档13.13)进行分页:

 通过使用带有过滤器的IQuery接口可以分页集合:

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

或者(从文件17.1.4):

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

这不像使用System.Linq方法那么流畅。我猜他们也会加入语法。


I read this article where Ayende states NHibernate can (compared to EF 4):

So I decided to put together a test case. I created the cliché Blog model as a simple demonstration, with two classes as follows:

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; }
}

My mappings files look like this:

<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>

My test case looks something like this:

        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);
                }
            }
        }

Using lazy="extra", the call to b.Posts.Count does do a SELECT COUNT(Id)... which is great. However, b.Posts.Skip(0).Take(5) just grabs all Posts for Blog.Id = ?id, and then LINQ on the application side is just taking the first 5 from the resulting collection.

What gives?

解决方案

I'm pretty sure (reading the comments) that he's talking about the CreateFilter of ISession.

You can do paging like this (from the docs 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();

Or (from the docs 17.1.4):

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

That's is not as smooth as using the System.Linq methods. I guess they'll join the syntax some time too.

这篇关于分页在一个延迟加载集合与NHibernate的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 21:37