NHibernate: no se puede establecer con éxito la carga diferida
-
20-08-2019 - |
Pregunta
Tengo una tabla Parent y una tabla Child. Child contiene una clave foránea para la tabla Parent, creando una relación de uno a muchos. Aquí hay una parte de mi mapeo que defino con fluidez 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();
}
}
Como puede ver, he configurado LazyLoad en la relación. Tenga en cuenta también que en mis clases de modelo, todas las propiedades se configuran como virtuales.
Ahora para la consulta simple:
ICriteria crit = Session.CreateCriteria(typeof(Child))
.Add(Expression.Eq("Id", 18));
IList<Child> list = crit.List<Child>();
Y el SQL generado:
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 puede ver, se une en la tabla principal y selecciona sus campos (id y descripción). Pero, ¿por qué hace eso ya que solicité lazyloading?
Ahora si cambio la consulta a:
ICriteria crit2 = Session.CreateCriteria(typeof(Child))
.SetFetchMode("Parent", FetchMode.Lazy)
.Add(Expression.Eq("Id", 18));
Se generan 2 consultas sql:
SELECT this_.ChildID as ChildID5_0_,
this_.ParentID as ParentID5_0_
FROM Childs this_
WHERE this_.ChildID = 18 /* @p0 */
lo cual es bueno para mí: no unirse, no se consulta la tabla principal. Pero también obtengo este segundo:
SELECT parent0_.ParentID as ParentID4_0_,
parent0_.Description as Descript2_4_0_
FROM Parents parent0_
WHERE parent0_.ParentID = 45 /* @p0 */
que consulta nuevamente la tabla principal.
Estas 2 consultas se generan durante la línea:
IList<Child> list = crit.List<Child>();
Soy totalmente ignorante de lo que sucede aquí. ¿Alguien puede ayudar?
Solución
Dependerá de su versión de Fluent NHibernate. Hasta cierto punto, era el valor predeterminado que todas las entidades no se cargarían de forma diferida. Esto es equivalente a establecer explícitamente lazy="false"
en su entidad. Este ya no es el caso, pero si está ejecutando algo antes de ese punto, verá este comportamiento.
La configuración de carga diferida de muchos a uno / referencias se anula por la carga diferida a nivel de entidad desde el objetivo, por lo que si está ejecutando en esta versión anterior de FNH, la configuración de entidad procesará su References(...).LazyLoad()
llamada discutible .
Debe verificar que está utilizando la última versión de FNH, eso debería arreglar las cosas; sin embargo, si no es así, debe establecer explícitamente la carga diferida en su entidad Parent
. Puede hacerlo con el método LazyLoad
en ClassMap<T>
.