Проблема с запросом NHinerbate - запрос соединения с неосновными ключами

Я новичок в Nhibernate, я пытаюсь использовать nhibernate в проекте и хотел преобразовать следующий sql-запрос в Nhibernate HQL? Возможен ли этот запрос в Nhibernate HQL / ICriteria?

SELECT     dbo.Table1.*
FROM         dbo.Table1 INNER JOIN
             dbo.Table2 ON dbo.Table1.Id2 = Table2.Id INNER JOIN
            dbo.Table2 AS T2 ON dbo.Table1.Id3 = T2.Id

это то, что я пробовал и потерпел неудачу. Я получаю исключение Ожидаемый путь для присоединения!

[from Table1 T1 inner join Table2 T2 inner join Table2 T3 where T1.Id2 = T2.Id and
          T1.Id3 = T3.Id]

Любая помощь будет оценена.

Изменить 1: добавление классов, которые я использую.

 public class Table1
{
  public virtual long Id {get;set;}
  public virtual Guid Id2 {get;set}
  public virtual Guid Id3 {get;set}

  other properties ....
}

public class Table2
{
  public virtual long primaryKey {get;set;}
  public virtual Guid Id {get;set;}

  other properties ....
}

Я не использовал экземпляр класса Table2 в классе Table1.

Спасибо,
Алекс


person wizzardz    schedule 22.11.2010    source источник
comment
Что такое a и e в вашем запросе HQL?   -  person Aleksandar Vucetic    schedule 22.11.2010
comment
ну, это была ошибка (это было из моего производственного кода, теперь он был удален)   -  person wizzardz    schedule 22.11.2010


Ответы (2)


В HQL вы не присоединяетесь к «таблицам». Вы запускаете запрос к первому классу и переходите к свойствам.

например:

class A
{
  B MyB { get; set; }
}

class B
{
}

Hql:

SELECT a FROM A a join MyB

MyB - это имя свойства.

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

Это может выглядеть примерно так:

SELECT t1
FROM T1 t1
   join MyT2 t2

Изменить:

Запрос к вашим классам будет выглядеть так:

SELECT t1
FROM Table1 t1, Table2 t2
WHERE t1.Id2 = t2.Id

Соединения нет, потому что в модели нет отношения. Вы можете присоединиться к нему только по перекрестному произведению и предложению where.

Вы не получите особой выгоды от NH, если не работаете с полезной моделью классов. Полезно означает, что вы можете перемещаться по модели, не обращаясь постоянно к базе данных. Когда вы просто пишете классы, которые выглядят как таблицы базы данных, вы не особо выиграете.

Ваши классы могут выглядеть так:

public class Class1
{
  public virtual long Id {get;set;}
  public virtual Class2 Class2 {get;set}

  other properties ....
}

public class Class2
{
  public virtual long primaryKey {get;set;}
  public virtual Guid Id {get;set;}

  other properties ....
}

Затем вы сопоставляете его как many-to-one, используя property-ref, чтобы указать ссылку на непервичный ключ.

person Stefan Steinegger    schedule 22.11.2010
comment
Привет, Стефан, спасибо за ответ. Я добавил образец модели классов, которые я использовал. - person wizzardz; 22.11.2010
comment
Обязательно ли иметь экземпляр класса B в классе A, даже если между таблицей A и таблицей B нет физической связи? - person wizzardz; 22.11.2010
comment
Даже если ограниченный FK не существует, вам все равно придется сопоставить свойство Id2 с классом Table2 вместо Guid, который вы представляете в своем сопоставлении. Идея, лежащая в основе NH, - это единственное, что вы знаете, это домен, и в HQL вы явно перемещаетесь по графику, а NH переводит это в фактический SQL. Таким образом, если свойство Id2 таблицы Table1 представляет собой идентификатор таблицы Table2, и вы хотите пройти по таблице Table2 в своем домене, вам придется сопоставить это свойство как объект типа Table2. - person Jaguar; 23.11.2010
comment
@wizzardz: добавляю еще один раздел. - person Stefan Steinegger; 24.11.2010
comment
Спасибо за ответ. Если вы видите мой запрос Sql, Id в таблице 2 относится к Id2 и Id3 в Table1. Итак, в классе модели Class1 мне нужно добавить другое свойство, например, общедоступный виртуальный Class2 ObjId3 {get; set} чтобы получить правильный запрос hql? - person wizzardz; 24.11.2010

Большое спасибо, Стефан, наконец-то я смог решить эту проблему.

Я попробую смоделировать проблему на другом примере. Надеюсь, он может быть полезен кому-нибудь еще.

Проблема: скажем, у меня есть две таблицы «Сотрудник» и «Проект», в таблице проекта есть два столбца «Лид» и «Менеджер», в которых будет храниться код сотрудника. Мне пришлось получить детали проекта на основе кода сотрудника «Менеджер» и «Лид».

Вот решение моей проблемы.
Файл сопоставления сотрудников.

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
       namespace="Learn.Models" assembly="Learn.Models">
  <class name="Employee" table="Employee">
    <id column="Id" type="Int64">
      <generator class="identity"></generator>
    </id>
    <property name="EntityId" column="EmployeeEntityId" not-null="true"></property>
    <property name="FirstName" column="FirstName" not-null="true"></property>
    <property name="LastName" column="LastName" not-null="true"></property>
    <property name="DateOfBirth" column="DateOfBirth" not-null="true"></property>
    <property name="EmpCode" column="EmpCode" not-null="true"></property>
  </class>
</hibernate-mapping>

Файл сопоставления проекта:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
       namespace="Learn.Models" assembly="Learn.Models">
  <class name="Project" table="Project">
    <id column="Id" type="Int64">
      <generator class="identity"></generator>
    </id>
    <property name="EntityId" column="ProjectEntityId" not-null="true"></property>
    <property name="ProjectName" column="ProjName" not-null="true"></property>

    <many-to-one name="ProjectManager" class="Employee" property-ref="EmpCode" column="Manager" lazy="proxy"></many-to-one>
    <many-to-one name="ProjectLead" class="Employee" property-ref="EmpCode" column="Lead" lazy="proxy"></many-to-one>
  </class>
</hibernate-mapping>

Класс сотрудника:

public class Employee : IEntity
{
    public Employee()
    {
    }

    public virtual long Id { get; set; }
    public virtual Guid EntityId { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual DateTime DateOfBirth { get; set; }
    public virtual string EmpCode { get; set; }
}

Класс проекта:

public class Project:IEntity
{
    public virtual string ProjectName { get; set; }

    public virtual Employee ProjectLead { get; set; }
    public virtual Employee ProjectManager { get; set; }

    public virtual long Id { get; set; }
    public virtual Guid EntityId { get; set; }

}

Мне нужно было получить детали проекта на основе кода сотрудников ProjectLead и ProjectManager, и это HQL-запрос, который я использовал.

string hql = "select p from Project p "
                + "join p.ProjectLead as lead "
                + "join p.ProjectManager as manager "
                + "where p.ProjectLead.EmpCode = 006 and "
                + "p.ProjectManager.EmpCode = 005";
person wizzardz    schedule 06.12.2010