Я представил сопоставление для бизнес-объекта, которое имеет (среди прочего) свойство с именем «Имя»:
public class Foo : BusinessObjectBase
{
...
public virtual string Name { get; set; }
}
По какой-то причине, когда я выбираю объекты "Foo", NHibernate, кажется, применяет отложенную загрузку свойств (для простых свойств, а не ассоциаций):
Следующий фрагмент кода генерирует n + 1 операторов SQL, из которых первый выбирает только идентификаторы, а остальные n выбирают имя для каждой записи:
ISession session = ...IQuery query = session.CreateQuery(queryString);
ITransaction tx = session.BeginTransaction();
List<Foo> result = new List<Foo>();
foreach (Foo foo in query.Enumerable())
{
result.Add(foo);
}
tx.Commit();
session.Close();
производит:
select foo0_.FOO_ID as col_0_0_ from V1_FOO foo0_
SELECT foo0_.FOO_ID as FOO1_2_0_, foo0_.NAME as NAME2_0_ FROM V1_FOO foo0_
WHERE foo0_.FOO_ID=:p0;:p0 = 81
SELECT foo0_.FOO_ID as FOO1_2_0_, foo0_.NAME as NAME2_0_ FROM V1_FOO foo0_
WHERE foo0_.FOO_ID=:p0;:p0 = 36470
SELECT foo0_.FOO_ID as FOO1_2_0_, foo0_.NAME as NAME2_0_ FROM V1_FOO foo0_
WHERE foo0_.FOO_ID=:p0;:p0 = 36473
Аналогично, следующий код приводит к исключению LazyLoadingException после закрытия сеанса:
ISession session = ...
ITransaction tx = session.BeginTransaction();
Foo result = session.Load<Foo>(id);
tx.Commit();
session.Close();
Console.WriteLine(result.Name);
После этого сообщения , "lazy properties ... редко является важной функцией, которую можно включить ... (и) в Hibernate 3, по умолчанию отключено."
Так что я делаю не так? Мне удалось обойти LazyLoadingException, выполнив NHibernateUtil.Initialize(foo)
, но еще хуже то, что n + 1 SQL-операторов, которые приносят мои приложение на колени.
Вот как выглядит отображение:
<class name="Foo" table="V1_FOO">
...
<property name="Name" column="NAME"/>
</class>
Кстати: абстрактный базовый класс BusinessObjectBase инкапсулирует свойство ID, которое служит внутренним идентификатором.