gpt4 book ai didi

c# - 使用 NHibernate 对延迟加载的集合进行分页

转载 作者:可可西里 更新时间:2023-11-01 08:10:47 24 4
gpt4 key购买 nike

我读了this article其中 Ayende 指出 NHibernate 可以(与 EF 4 相比):

  • Collection with lazy=”extra” – Lazy extra means that NHibernate adapts to the operations that you might run on top of your collections. That means that blog.Posts.Count will not force a load of the entire collection, but rather would create a “select count(*) from Posts where BlogId = 1” statement, and that blog.Posts.Contains() will likewise result in a single query rather than paying the price of loading the entire collection to memory.
  • Collection filters and paged collections - this allows you to define additional filters (including paging!) on top of your entities collections, which means that you can easily page through the blog.Posts collection, and not have to load the entire thing into memory.

所以我决定整理一个测试用例。我创建了陈词滥调的博客模型作为一个简单的演示,有两个类如下:

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

使用 lazy="extra",对 b.Posts.Count 的调用会执行 SELECT COUNT(Id)...这很棒。但是,b.Posts.Skip(0).Take(5) 只是获取 Blog.Id = ?id 的所有帖子,然后应用程序端的 LINQ 只是从结果中获取前 5 个收藏。

什么给了?

最佳答案

我很确定(阅读评论)他在谈论 ISession 的 CreateFilter。

您可以像这样进行分页(来自文档 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 方法那样顺利。我想他们也会在某个时候加入语法。

关于c# - 使用 NHibernate 对延迟加载的集合进行分页,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2430863/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com