NHibernate 3.2 LINQ n+1 解决方案

4

我使用带有LINQ的NHibernate 3.2,在SQL中进行n+1个查询。在映射中使用fetch设置为“join”。当我使用criteria时,只有一个select查询。此外,我找不到一些例子中看到的Fetch()FetchMany()方法。是否存在使用Linq to NHibernate 3.2解决n+1问题的方法?

我的代码简化版本如下:

class News
{
    public virtual int Id { get; protected set; }
    public virtual DateTime Date { get; set; }
    public virtual Category Category { get; set; }
}

class Category
{
    public virtual int Id { get; protected set; }
    public virtual ISet<News> News { get; set; }
}

映射:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="News" namespace="NewsManagement.Models">
<class name="News" table="News">
<id name="Id">
        <generator class="native" />
</id>
<property name="Date" not-null="true" />
<many-to-one name="Category" fetch="join" column="CategoryId" class="Category, NHibernateManyToOne" not-null="true"/>
</class>
</hibernate-mapping>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="News" namespace="NewsManagement.Models">
<class name="Category" table="Categories">
    <id name="Id" column="Id">
        <generator class="native" />
    </id>
    <set name="News" fetch="join" cascade="all-delete-orphan">
        <key column="CategoryId" />
        <one-to-many class="News, NHibernateOneToMany" /> 
    </set>
</class>
</hibernate-mapping>

导致多个查询的查询:

var news = newsRepository.Linq().Skip(DefaultPageSize*currentPageIndex).Take(DefaultPageSize).OrderByDescending(x => x.Date).ToList();

这就是没有冗余选择的方法:
var criteria = Session.CreateCriteria<News>();
criteria = criteria.AddOrder(Order.Desc(property));
criteria = criteria.SetMaxResults(pageSize).SetFirstResult((pageNumber - 1)*pageSize);
var news = criteria.List<News>();

也许我们可以看一下您正在使用哪个实体以及您想要执行哪个查询... - Felice Pollano
@FelicePollano 抱歉,现在代码已经在这里了。 - Arсiom Prudnikaŭ
2个回答

6
尝试使用以下内容:
criteria.SetFetchMode("Category",FetchMode.Eager);

或者使用Linq:
session.Query<News>()
                .Fetch(k => k.Category)
                .Skip(n)
                .Take(m)

或者,您可以使用QueryOver:

var result = session.QueryOver<News>
                    .Fetch(x => x.Category).Eager
                    .List();

这是一个标准,但我需要使用LINQ。 - Arсiom Prudnikaŭ
非常感谢。我的错误在于我错误地使用了Linq,这就是为什么我看不到Fetch的原因。 - Arсiom Prudnikaŭ
+1 for LINQ,QueryOver和Criteria...我们有多种选择! :) - Jess

1
var result = session.Query<News>()
                    .Fetch(x => x.Category)
                    .ToList();

这是你想要的吗?

.Query 存在于 using NHibernate.Linq; 中。

或者你也可以使用 QueryOver<T>

它看起来会像这样:

var result = session.QueryOver<News>
                    .Fetch(x => x.Category).Eager
                    .List();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接