Nhibernate SetFetchMode - 内部与左外部联接

时间:2014-09-18 17:51:16

标签: c# nhibernate nhibernate-mapping nhibernate-criteria

所有

我有一个名为Client的实体,它与名为Region的实体有关联:

客户 - >区域

我的所有实体都是Lazy加载的(nhibernate默认设置)。

客户端中的

区域映射为NotNull = false:

[ManyToOne(Column = "region_id",
                ClassType = typeof(Region),
                NotNull = false)]
    public virtual Region Region
    {
        get { return _region; }
        set { _region = value; }
    }

当我创建客户端条件并设置FetchMode(FetchMode.Join)时,生成的select是一个内连接,但是我预期并且离开外连接,因为Region可以为NULL。

上述情况发生在如何创建标准上。如果我在Ex 1中创建标准,我会生成正确的SQL并且Region保持外部连接,如果我在Ex 2中创建条件,则生成错误的SQL,Region是内部连接的。

Ex 1)正确的SQL

ICriteria c = s.Session.CreateCriteria<Client>();
    c.SetFetchMode("Region", NHibernate.FetchMode.Join);
    IList<Client> list2 = c.List<Client>();

SELECT *  FROM Companies this_  left outer join Code_Region_Types region2_ on this_.region_id=region2_.entity_id

Ex 2)SQL不正确

ICriteria c = s.Session.CreateCriteria<Client>();
    ICriteria subC = c.CreateCriteria("Region");
    c.SetFetchMode("Region", NHibernate.FetchMode.Join);
    IList<Client> list2 = c.List<Client>();

SELECT * FROM Companies this_ inner join Code_Region_Types region1_ on this_.region_id=region1_.entity_id

在前2)中,创建子标准的行

ICriteria subC = c.CreateCriteria("Region");

弄乱了加入条款。

这会产生不正确的结果,因为某些客户端可能没有Region,因此不包含在查询中。

似乎唯一的解决方法是明确指定子标准的连接:

ICriteria subC = c.CreateCriteria("Region", JoinType.LeftOuterJoin)

以上解决了这个问题。这是Nhibernate所期望的吗?

1 个答案:

答案 0 :(得分:3)

您所遇到的是绝对正确的。而你的解决方案确实是正确的。

致电:

criteria.CreateCriteria(associationPath); 

实际上内部使用INNER JOIN(参见here):

public ICriteria CreateCriteria(string associationPath)
{
    return CreateCriteria(associationPath, JoinType.InnerJoin);
}

所以,这样就定义了Query。这将是INNER JOIN。然后,获取模式由 Criteria 及其 SubCriteria 的结果驱动 - 即仅考虑找到结果。

但是,正如您已经发现的那样,我们可以通过显式调用来改变它:

ICriteria subCriteria = criteria
     .CreateCriteria(associationPath, JoinType.LeftOuterJoin)

那将会做出预期的......