使用错误列的NH4 LINQ查询一对一

时间:2015-08-20 19:19:51

标签: nhibernate linq-to-nhibernate nhibernate-4

我在两个表之间有一对一的关系,我希望能够创建一个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)

1 个答案:

答案 0 :(得分:0)

只是从原始问题中列出我的评论(略微适合答案),因为这些似乎帮助了问题的作者

  1. 尝试将您的Linq查询更改为nh.Query<ConcreteClass>(cc => cc.AuxiliaryClass.AuxiliaryClassId > 0);,假设AuxiliaryClassId类型为int
  2. 当您想要提取ConcreteClass中但AuxiliaryClass中不存在的记录时,上述操作无效。为此你可能想要使用左外连接。如果你确实离开了外连接,那么你可以通过QueryOver(或Linq以一种不那么直接的方式)来做,然后在代码中检查无效性。根据您加载的数据集的大小,这在生产中可能不是一件好事。我不确定子查询如何实现你想要实现的目标
  3. 如果LINQ是唯一的选项,那么您可以使用DefaultIfEmpty方法在LINQ中获得左外连接。这个SO question应该是一个很好的起点。
  4. 最后,在这种情况下,普通的SQL可能是最有效的。如果您想沿着该路线走,那么您可以使用ISession.CreateSQLQuery并按原样使用SQL查询