NHibernate: невозможно успешно установить отложенную загрузку - PullRequest
2 голосов
/ 24 января 2009

У меня есть таблица 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>();

Я совершенно не знаю, что здесь происходит. Может кто-нибудь помочь?

1 Ответ

6 голосов
/ 26 января 2009

Это будет зависеть от вашей версии Fluent NHibernate. До определенного момента по умолчанию все объекты , а не загружались лениво. Это эквивалентно явной установке lazy="false" в вашей сущности. Это больше не так, но если вы работаете на чем-то до этого момента, вы увидите это поведение.

Параметр отложенной загрузки многие-к-одному / ссылками переопределяется отложенной загрузкой уровня объекта от цели, поэтому, если вы работаете в этой более старой версии FNH, тогда параметр объекта будет отрисовывать ваш References(...).LazyLoad() вызов .

Вам необходимо убедиться, что вы используете последнюю версию FNH, которая должна исправить ситуацию; однако, если это не так, вам нужно явно включить отложенную загрузку в вашей сущности Parent. Вы можете сделать это с помощью метода LazyLoad на ClassMap<T>.

...