NH4 LINQ Запрос с использованием неправильного столбца для одного к одному

У меня есть отношение один к одному между двумя таблицами, и я хочу иметь возможность создать запрос LINQ, который будет возвращать "родительские" таблицы, где есть что-то в дочерней таблице. Проблема заключается в том, что запрос NH, который генерирует, проверяет, не является ли идентификатор родительской таблицы нулевым (и никогда не является), а не присоединяется к дочерней таблице. Это независимо от того, использую я ленивую или не ленивую загрузку. Я использую пользовательские соглашения об автоматах с переопределением, но вот генерируемый XML HBM:

Отображение для абстрактного класса, конкретного класса, который является родительским

<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

Если я отключаю отложенную загрузку, соединения присоединяются к вспомогательной таблице, но все равно сравнивают идентификатор таблицы конкретного класса с нулем.

редактировать

Предложение Per @Suhas:

Попробуйте изменить свой запрос Linq на nh.Query(cc => cc.AuxiliClass.AuxiliClassId > 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 ответ

Просто перечислил мои комментарии (слегка адаптированные к ответу) из исходных вопросов, поскольку те, кажется, помогли автору вопроса

  1. Попробуйте изменить свой запрос Linq на nh.Query<ConcreteClass>(cc => cc.AuxiliaryClass.AuxiliaryClassId > 0); при условии, AuxiliaryClassId имеет тип int
  2. Выше не будет работать, если вы хотите получить записи, присутствующие в ConcreteClass но не присутствует в AuxiliaryClass, Для этого вы можете использовать левое внешнее соединение. Если вы выполняете левое внешнее соединение, то вы можете сделать это через QueryOver (или Linq не таким прямым способом), а затем выполнить проверку на нуль в вашем коде. В зависимости от размера набора данных, который вы загружаете, это может быть нехорошо в производственной среде. Я не уверен, как бы сделать подзапрос, чтобы достичь того, что вы пытаетесь достичь
  3. если LINQ является единственным вариантом, то вы можете использовать DefaultIfEmpty метод для получения левого внешнего соединения в LINQ. Этот ТАК вопрос должен быть хорошей отправной точкой.
  4. Наконец, простой SQL может быть наиболее эффективным в этой ситуации. Если вы хотите пойти по этому маршруту, то вы можете использовать ISession.CreateSQLQuery и использовать ваш SQL-запрос как есть
Другие вопросы по тегам