2015-08-20 1 views
0

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

Mapping для абстрактного класса, Класс бетона, которого Родитель

<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> 

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.AuxiliaryClass.AuxiliaryClassId> 0); при условии, AuxiliaryClassId имеет тип междунар

Я на самом деле сделал 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

Попробуйте изменить запрос Linq для 'nh.Query (сс => cc.AuxiliaryClass.AuxiliaryClassId> 0) ; 'предполагается, что' AuxiliaryClassId' имеет тип 'int' – Suhas

+0

Спасибо, @Suhas. Я обновил свой вопрос в результате попытки этого. 'AuxiliaryClassId' -' Int32? '. –

+0

Я не знаю, чего вы пытаетесь достичь с помощью нового запроса. Но прежде чем мы получим этот момент, скажите мне, как бы вы написали SQL для достижения того, чего вы пытаетесь достичь, не думая о NH или LINQ на мгновение? – Suhas

ответ

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 запрос как
Смежные вопросы