2

我有一个表 Parent 和一个表 Child。Child 包含 Parent 表的外键,创建一对多关系。这是我用 fluent 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();
    }
}

如您所见,我已经在关系上设置了 LazyLoad。另请注意,在我的模型类中,所有属性都设置为虚拟。

现在进行简单查询:

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

并且生成的SQL:

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

如您所见,它在 Parent 表上进行连接并选择其字段(id 和 description)。但是,既然我要求延迟加载,为什么它会这样做呢?

现在,如果我将查询更改为:

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

生成了 2 个 sql 查询:

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

这对我有好处:不加入,不查询父表。但我也得到了第二个:

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

再次查询 Parent 表。

这 2 个查询是在行期间生成的:

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

我完全不知道这里发生了什么。有人可以帮忙吗?

4

1 回答 1

6

这取决于您的 Fluent NHibernate 版本。直到某一点,默认情况下所有实体都不会被延迟加载。这相当于lazy="false"在您的实体中显式设置。现在不再是这种情况,但是如果您在此之前运行任何东西,那么您会看到这种行为。

多对一/引用延迟加载设置会被来自目标的实体级延迟加载覆盖,因此如果您在此旧版本的 FNH 上运行,那么实体设置将使您的References(...).LazyLoad()呼叫没有实际意义。

您需要验证您使用的是最新版本的 FNH,这应该可以解决问题;但是,如果没有,那么您需要在您的Parent实体中显式设置延迟加载。您可以LazyLoad使用ClassMap<T>.

于 2009-01-26T12:19:57.320 回答