HQL-запрос к подклассам - PullRequest
5 голосов
/ 09 июня 2010

В моей модели сущностей определены следующие сущности:

public class MyContainer
{
   public virtual ICollection<Base> Subs { get; set; }
}

public abstract class Base
{
   public virtual Guid Id { get; set; }
}
public abstract class Sub1 : Base
{
   public virtual int MyValue { get; set; }
}
public abstract class Sub2 : Base
{
   public virtual int MyValue { get; set; }
}

и следующие сопоставления FluentNHibernate для вышеуказанных сущностей:

public sealed class BaseMap : ClassMap<Base>
{
   public BaseMap()
   {
      Table("BaseTable");
      Id(e => e.Id);
   }
}

public sealed class Sub1Map : SubClassMap<Sub1>
{
   public Sub1Map()
   {
      Table("Sub1Table");
      KeyColumn("BaseId");

      Map(e => e.Myvalue);
   }
}

public sealed class Sub2Map : SubClassMap<Sub2>
{
   public Sub2Map()
   {
      Table("Sub2Table");
      KeyColumn("BaseId");

      Map(e => e.Myvalue);
   }
}

Когда я запускаю следующий HQL:

select sub
   from MyContainer container
        join fetch container.Subs sub
   where sub.MyValue = :p1

сгенерированный SQL применяет ограничение в предложении WHERE только для одного из подклассов, однако сгенерированные соединения являются правильными, т. Е. Генерируется следующий скелетный SQL:

SELECT ...
FROM BaseTable bt
     INNER JOIN Sub1Table st1 ON ...
     INNER JOIN Sub2Table st2 ON ...
WHERE st1.MyValue = @p1

где, как я ожидал, в операторе WHERE добавлено ИЛИ:

SELECT ...
FROM BaseTable bt
     INNER JOIN Sub1Table st1 ON ...
     INNER JOIN Sub2Table st2 ON ...
WHERE st1.MyValue = @p1
      OR st2.MyValue = @p2

Есть ли что-то, чего мне не хватает, или есть способ переписать HQL, чтобы я мог ссылатьсякаждый подкласс в предложении WHERE и применять ограничение напрямую (при условии, что оно затем сгенерирует дополнительное ограничение в сгенерированном SQL)?

Я использую NHibernate 3.0.0.

1 Ответ

1 голос
/ 26 апреля 2011

MyValue должно быть объявлено и отображено в Base. Невозможно отфильтровать базовый класс по свойствам, которые определены в подклассах, без приведения к конкретному классу:

where (b.class = Sub1 and b.MyValue = :p1) or (b.class = Sub2 and b.MyValue = :p1)

EDIT: Или в FNH1.2 может использоваться объединение подклассов:

public class BaseMap : ClassMap<Base>
{
    public BaseMap()
    {
        UseUnionSubclassForInheritanceMapping();
        Table("BaseTable");
        Id(e => e.Id);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...