问题描述
我阅读了其中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在应用程序端
您可以这样(从文档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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!