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?

¿Fue útil?

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>.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top