Pergunta

Eu tenho um pai de mesa e um filho da mesa. A criança contém uma chave estrangeira à mesa dos pais, criando um relacionamento um para muitos. Aqui está uma parte do meu mapeamento que defino com Nibernato fluente:

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();
    }
}

Como você pode ver, defina o Lazyload na relação. Observe também que, nas minhas classes de modelo, todas as propriedades são definidas como virtuais.

Agora, para a consulta simples:

ICriteria crit = Session.CreateCriteria(typeof(Child))
    .Add(Expression.Eq("Id", 18));
IList<Child> list = crit.List<Child>();

E o SQL gerado:

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 */

Como você pode ver, ele entra na tabela pai e seleciona seus campos (ID e descrição). Mas por que faz isso desde que solicitei o Lazyloading?

Agora, se eu mudar a consulta para:

ICriteria crit2 = Session.CreateCriteria(typeof(Child))
    .SetFetchMode("Parent", FetchMode.Lazy)
    .Add(Expression.Eq("Id", 18));

Existem 2 consultas SQL geradas:

SELECT this_.ChildID  as ChildID5_0_,
       this_.ParentID as ParentID5_0_
FROM   Childs this_
WHERE  this_.ChildID = 18 /* @p0 */

O que é bom para mim: sem ingressar, a tabela pai não é consultada. Mas eu entendo este segundo também:

SELECT parent0_.ParentID    as ParentID4_0_,
       parent0_.Description as Descript2_4_0_
FROM   Parents parent0_
WHERE  parent0_.ParentID = 45 /* @p0 */

que novamente consulta a tabela pai.

Essas duas consultas são geradas durante a linha:

IList<Child> list = crit.List<Child>();

Estou totalmente ignorante do que acontece aqui. Alguém pode ajudar?

Foi útil?

Solução

Isso dependerá da sua versão do Fluent Nibernate. Até um certo ponto, era o padrão que todas as entidades iriam não ser preguiçoso carregado. Este é o equivalente a definir explicitamente lazy="false" em sua entidade. Esse não é mais o caso, mas se você estiver executando qualquer coisa antes desse ponto, verá esse comportamento.

A configuração de carga preguiçosa de muitos para um/one/referências é substituída pelo nível da entidade, carga preguiçosa do alvo; portanto, se você estiver executando nesta versão mais antiga do FNH, a configuração da entidade estará renderizando seu References(...).LazyLoad() Ligue para o Moot.

Você precisa verificar se está na versão mais recente do FNH, que deve consertar as coisas; No entanto, se não acontecer, você precisa definir explicitamente o carregamento preguiçoso em seu Parent entidade. Você pode fazer isso com o LazyLoad Método no ClassMap<T>.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top