将NHibernate开放会话整合到数据库(耦合NHibernate和数据库会话)

时间:2010-01-25 14:40:54

标签: database nhibernate orm

我们将NHibernate用于ORM,在我们程序的初始化阶段,我们需要从DB加载一些类T的许多实例。

在我们的应用程序中,以下代码将提取所有这些实例:

public IList<T> GetAllWithoutTransaction()
{
    using (ISession session = GetSession())
    {
        IList<T> entities = session
            .CreateCriteria(typeof(T))
            .List<T>();
        return entities;
        }
    }
}

使用NHibernate日志我发现框架使用的实际SQL查询是:

{
    Load a bunch of rows from a few tables in the DB (one SELECT statement).

    for each instance of class T
    {
        Load all the data for this instance of class T from the abovementioned rows 
        (3 SELECT statements).
    }
}

3个选择语句被耦合,即第二个依赖于第一个,第三个依赖于前两个。 正如您所看到的,SELECT语句的数量是数百万,这给我们带来了巨大的开销,直接来自所有这些对DB的调用(每个调用需要“开放数据库会话”,“关闭数据库会话”,...... ),即使我们使用的是单个NHibernate会话。

我的问题是: 我想以某种方式将所有SELECT语句合并为一个大的SELECT语句。我们没有运行多线程,也没有在初始阶段以任何方式改变数据库。

这样做的一种方法是定义我自己的对象并使用NHibernate映射它,它将被快速加载并在一个查询中加载所有内容,但它需要我们自己实现这些语句中使用的连接操作,以及更糟糕 - 打破ORM抽象。 有没有办法通过某种配置来做到这一点?

谢谢你们!

2 个答案:

答案 0 :(得分:3)

这被称为SELECT N+1 problem。您需要决定放置连接的位置(FetchMode.Eager)

答案 1 :(得分:0)

如果您可以在SQL中将查询编写为单个查询,则可以让NHibernate将其作为单个查询执行(通常不会破坏抽象)。

当你在这个场景中真正想要的是加载时,你可能会有一些关系/类设置为延迟加载。

NHibernate文档中有很多关于此的信息。你可能想从这里开始:

http://www.nhforge.org/doc/nh/en/index.html#performance-fetching

相关问题