NHibernate: impossibile impostare il caricamento lento
-
20-08-2019 - |
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?
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>
.