Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用NHibernate在延迟加载的集合上分页_C#_Nhibernate_Collections_Pagination_Lazy Loading - Fatal编程技术网

C# 使用NHibernate在延迟加载的集合上分页

C# 使用NHibernate在延迟加载的集合上分页,c#,nhibernate,collections,pagination,lazy-loading,C#,Nhibernate,Collections,Pagination,Lazy Loading,我阅读了Ayende州NHibernate与EF 4的比较: 带有lazy=“extra”的集合–lazy extra表示NHibernate适应 您可能运行的操作 你的收藏之首。这意味着 该blog.Posts.Count不会强制 加载整个集合,但 而是创建一个“选择计数”* 来自BlogId=1”的帖子 声明,以及 blog.Posts.Contains也将如此 结果是一个查询,而不是 支付装载整个系统的费用 收集到内存。 集合筛选器和分页集合-这允许您 定义其他过滤器,包括 传呼!在你的实

我阅读了Ayende州NHibernate与EF 4的比较:

带有lazy=“extra”的集合–lazy extra表示NHibernate适应 您可能运行的操作 你的收藏之首。这意味着 该blog.Posts.Count不会强制 加载整个集合,但 而是创建一个“选择计数”* 来自BlogId=1”的帖子 声明,以及 blog.Posts.Contains也将如此 结果是一个查询,而不是 支付装载整个系统的费用 收集到内存。 集合筛选器和分页集合-这允许您 定义其他过滤器,包括 传呼!在你的实体之上 收藏,这意味着你可以 轻松浏览blog.Posts 集合,而不必加载 把整件事记在记忆里。 所以我决定编写一个测试用例。我创建了一个陈词滥调的博客模型,作为一个简单的演示,有两个类,如下所示:

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; }
}
我的映射文件如下所示:

<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>
        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);
                }
            }
        }
我的测试用例如下所示:

<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>
        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);
                }
            }
        }
使用lazy=extra,对b.Posts.Count的调用会执行SELECT COUNTId。。。这很好。然而,b.Posts.Skip0.Take5只是获取Blog.Id=?Id的所有帖子,然后应用程序端的LINQ只是从结果集合中获取前5篇


给出了什么?

我很肯定读到了他在谈论ISession的CreateFilter的评论

您可以在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();
或参考文件17.1.4:

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

这并不像使用System.Linq方法那样平滑。我想他们以后也会加入语法。

+1问个好问题。我一直在想NHibernate的惰性加载功能有一段时间了,但还没有时间尝试它们。也许关于集合过滤器的LINQ到NHibernate部分没有实现,只是使用lazy=extra的一个警告。我们开始在我们的应用程序上使用它,并且一切正常,直到我们部署到一台Sql Server 2000机器上,这台机器仍然是客户认可的软件。因为我们使用guid作为标识字段,所以我们开始得到一个异常,“无法对唯一标识符执行计数”。我查看了NH源代码,发现是额外的延迟加载选择了第一个键列并执行了“选择计数”,这是我们的guid字段。嗯,是的。令人失望的不顺利。但是,那就行了。谢谢。嗨,有没有可能发布原始示例,并实现此技术?谢谢