Domanda

Ho una tabella Parent e una tabella Child. Child contiene una chiave esterna per la tabella Parent, creando una relazione uno-a-molti. Ecco una parte della mia mappatura che definisco con NHibernate 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();
    }
}

Come puoi vedere, ho impostato LazyLoad sulla relazione. Nota anche che nelle mie classi di modello, tutte le proprietà sono impostate come virtuali.

Ora per la query semplice:

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

E l'SQL generato:

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

Come puoi vedere, fa un join sulla tabella Parent e seleziona i suoi campi (id e descrizione). Ma perché lo fa da quando ho richiesto lazyloading?

Ora se cambio la query in:

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

Sono state generate 2 query sql:

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

che è buono per me: nessun join, la tabella Parent non viene interrogata. Ma ho anche questo secondo:

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

che interroga nuovamente la tabella Parent.

Queste 2 query sono generate durante la riga:

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

Sono totalmente ignaro di ciò che accade qui. Qualcuno può aiutare?

È stato utile?

Soluzione

Dipenderà dalla tua versione di Fluente NHibernate. Fino a un certo punto era l'impostazione predefinita che tutte le entità non sarebbero state caricate in modo pigro. Questo è l'equivalente dell'impostazione esplicita lazy="false" nella tua entità. Questo non è più il caso, ma se stai eseguendo qualcosa prima di quel punto, vedrai questo comportamento.

L'impostazione del carico pigro molti-a-uno / riferimenti viene sovrascritta dal carico pigro a livello di entità dalla destinazione, quindi se si sta eseguendo questa versione precedente di FNH, l'impostazione dell'entità renderà il tuo References(...).LazyLoad() moot di chiamate .

Devi verificare di essere sull'ultima versione di FNH, che dovrebbe risolvere le cose; tuttavia, in caso contrario, devi attivare esplicitamente il caricamento lento nella tua Parent entità. Puoi farlo con il metodo LazyLoad su ClassMap<T>.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top