У меня есть таблица Parent и таблица Child. Дочерний объект содержит внешний ключ для родительской таблицы, создавая отношение «один ко многим». Вот часть моего отображения, которое я определяю с помощью беглого NHibernate:
public class ParentMap : ClassMap<Parent>
{
public ParentMap()
{
WithTable("Parents");
Id(x => x.Id, "ParentID")
.WithUnsavedValue(0)
.GeneratedBy.Identity();
Map(x => x.Description, "Description");
HasMany<Child>(x => x.Childs)
.LazyLoad()
.WithKeyColumn("ParentID")
.IsInverse()
.AsSet();
}
}
public class ChildMap : ClassMap<Child>
{
public ChildMap()
{
WithTable("Childs");
Id(x => x.Id, "ChildID")
.WithUnsavedValue(0)
.GeneratedBy.Identity();
References(x => x.Parent, "ParentID")
.CanNotBeNull()
.LazyLoad();
}
}
Как видите, я установил LazyLoad для отношения. Также обратите внимание, что в моих модельных классах все свойства установлены как виртуальные.
Теперь простой запрос:
ICriteria crit = Session.CreateCriteria(typeof(Child))
.Add(Expression.Eq("Id", 18));
IList<Child> list = crit.List<Child>();
И сгенерированный SQL:
SELECT this_.ChildID as ChildID5_1_,
this_.ParentID as ParentID5_1_,
parent2_.ParentID as ParentID4_0_,
parent2_.Description as Descript2_4_0_
FROM Childs this_
inner join Parents parent2_
on this_.ParentID = parent2_.ParentID
WHERE this_.ChildID = 18 /* @p0 */
Как видите, он выполняет объединение в родительской таблице и выбирает ее поля (идентификатор и описание). Но почему это происходит, так как я просил ленивую загрузку?
Теперь, если я изменю запрос на:
ICriteria crit2 = Session.CreateCriteria(typeof(Child))
.SetFetchMode("Parent", FetchMode.Lazy)
.Add(Expression.Eq("Id", 18));
Сгенерировано 2 запроса sql:
SELECT this_.ChildID as ChildID5_0_,
this_.ParentID as ParentID5_0_
FROM Childs this_
WHERE this_.ChildID = 18 /* @p0 */
что хорошо для меня: нет соединения, родительская таблица не запрашивается.
Но я тоже получаю второй:
SELECT parent0_.ParentID as ParentID4_0_,
parent0_.Description as Descript2_4_0_
FROM Parents parent0_
WHERE parent0_.ParentID = 45 /* @p0 */
, который снова запрашивает родительскую таблицу.
Эти 2 запроса генерируются в строке:
IList<Child> list = crit.List<Child>();
Я совершенно не знаю, что здесь происходит. Может кто-нибудь помочь?