Консолидация открытых сессий NHibernate с БД (связывание сессий NHibernate и БД) - PullRequest
1 голос
/ 25 января 2010

Мы используем NHibernate для ORM, и на этапе инициализации нашей программы нам нужно загрузить много экземпляров некоторого класса 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 исчисляется миллионами, что дает нам огромные накладные расходы, которые возникают в результате всех этих обращений к БД (каждый из которых влечет за собой «открытый сеанс БД», «закрытый сеанс БД», ... ), даже если мы используем один сеанс NHibernate.

Мой вопрос такой: Я хотел бы как-то объединить все эти операторы SELECT в один большой оператор SELECT. Мы не работаем с многопоточными и никак не изменяем БД на этапе инициализации.

Один из способов сделать это - определить мой собственный объект и отобразить его с помощью NHibernate, который будет загружаться быстро и загружать все в одном запросе, но для этого потребуется, чтобы мы сами реализовали операции соединения, используемые в этих операторах, и хуже - ломает абстракцию ORM. Есть ли способ сделать это с помощью какой-либо конфигурации?

Спасибо, ребята!

Ответы [ 2 ]

3 голосов
/ 25 января 2010

Это называется проблемой SELECT N + 1 . Вам нужно решить, где вы будете размещать свои объединения (FetchMode.Eager)

0 голосов
/ 25 января 2010

Если вы можете написать запрос как отдельный запрос в SQL, вы можете заставить NHibernate выполнить его как один запрос (обычно без прерывания абстракции).

Вероятно, у вас есть некоторые отношения / классы, настроенные на ленивую загрузку, когда вы действительно хотите в этом сценарии загружать.

В документации NHibernate есть много хорошей информации об этом. Вы можете начать здесь:

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...