我在两个表之间有一对一的关系,我希望能够创建一个LINQ查询,它将返回" parent"子表中有某些内容的表。问题是NH正在生成的查询是检查父表的ID是否为空(并且它永远不是)而不是加入子表。无论我是使用懒惰还是非延迟加载,这都是无关紧要的。我使用自定义自动化约定和覆盖,但这里是生成的HBM XML:
抽象类的映射,父类的具体类
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="AbstractClass, DomainObjects, Version=2.2.1.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa" table="ABSTRACT_CLASS">
<id name="AbstractClassId" type="System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="ABSTRACT_CLASS_ID" />
<generator class="identity" />
</id>
<joined-subclass name="ConcreteClass, DomainObjects, Version=2.2.1.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa" table="CONCRETE_CLASS">
<key>
<column name="ABSTRACT_CLASS_ID" />
</key>
<one-to-one cascade="none" class="AuxiliaryClass, DomainObjects, Version=2.2.1.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa" name="AuxiliaryClass" property-ref="Foo" />
</joined-subclass>
</class>
</hibernate-mapping>
子表的映射
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
<class xmlns="urn:nhibernate-mapping-2.2" name="AuxiliaryClass, DomainObjects, Version=2.2.1.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa" table="AUXILIARY_CLASS">
<id name="AuxiliaryClassiD" type="System.Nullable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<column name="AUXILIARY_CLASS_ID" />
<generator class="identity" />
</id>
<many-to-one class="ConcreteClass, DomainObjects, Version=2.2.1.0, Culture=neutral, PublicKeyToken=aaaaaaaaaaaaaaaa" name="Foo">
<column name="FOO_ABSTRACT_CLASS_ID" />
</many-to-one>
</class>
</hibernate-mapping>
课程定义
public abstract class AbstractClass
{
public virtual Int32? AbstractClassId { get; set; }
}
public class ConcreteClass : AbstractClass
{
public virtual AuxiliaryClass AuxiliaryClass { get; set; }
}
public class AuxiliaryClass
{
public virtual Int32? AuxiliaryClassId { get; set; }
public virtual ConcreteClass Foo { get; set; }
}
不起作用的LINQ查询是:
nh.Query<ConcreteClass>().Where(cc => cc.AuxiliaryClass != null);
正在生成的查询是:
select
concretecl0_.CONCRETE_CLASS_ID as CONCRETE1_0_
from
CONCRETE_CLASS concretecl0_
inner join
ABSTRACT_CLASS concretecl0_1_
on
concretecl0_.ABSTRACT_CLASS_ID=concretecl0_1_.ABSTRACT_CLASS_ID
where
concretecl0_.ABSTRACT_CLASS_ID is not null
如果我关闭延迟加载,则会加入辅助表,但仍会将具体类的表ID与null进行比较。
修改
Per @ Suhas的建议:
尝试将您的Linq查询更改为nh.Query(cc =&gt; cc.AuxiliaryClass.AuxiliaryClassId&gt; 0);假设AuxiliaryClassId的类型为int
我实际上做了cc => cc.AuxiliaryClass.AuxiliaryClassId != null
,它有效,给我这个查询:
select
concretecl0_.ABSTRACT_CLASS_ID as concretecl0_1_0_
from
CONCRETE_CLASS concretecl0_
inner join
ABSTRACT_CLASS concretecl0_1_
on
concretecl0_.concretecl0_=concretecl0_1_.concretecl0_
, AUXILIARY_CLASS auxiliaryc1_
where
concretecl0_.ABSTRACT_CLASS_ID=auxiliaryc1_.FOO_ABSTRACT_CLASS_ID
and (auxiliaryc1_.AUXILIARY_CLASS_ID is not null)
但是,当我尝试使用反例cc => cc.AuxiliaryClass.AuxiliaryClassId == null
时,我得到了一个不起作用的查询:
select
concretecl0_.ABSTRACT_CLASS_ID as concretecl0_1_0_
from
CONCRETE_CLASS concretecl0_
inner join
ABSTRACT_CLASS concretecl0_1_
on
concretecl0_.concretecl0_=concretecl0_1_.concretecl0_
, AUXILIARY_CLASS auxiliaryc1_
where
concretecl0_.ABSTRACT_CLASS_ID=auxiliaryc1_.FOO_ABSTRACT_CLASS_ID
and (auxiliaryc1_.AUXILIARY_CLASS_ID is null)
答案 0 :(得分:0)
只是从原始问题中列出我的评论(略微适合答案),因为这些似乎帮助了问题的作者
nh.Query<ConcreteClass>(cc => cc.AuxiliaryClass.AuxiliaryClassId > 0);
,假设AuxiliaryClassId
类型为int
ConcreteClass
中但AuxiliaryClass
中不存在的记录时,上述操作无效。为此你可能想要使用左外连接。如果你确实离开了外连接,那么你可以通过QueryOver(或Linq以一种不那么直接的方式)来做,然后在代码中检查无效性。根据您加载的数据集的大小,这在生产中可能不是一件好事。我不确定子查询如何实现你想要实现的目标DefaultIfEmpty
方法在LINQ中获得左外连接。这个SO question应该是一个很好的起点。 ISession.CreateSQLQuery
并按原样使用SQL查询