所有
我有一个名为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所期望的吗?
答案 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)
那将会做出预期的......