NHinerbate查询问题 - 使用非主键加入查询

时间:2010-11-22 07:26:45

标签: nhibernate hql

我是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 ....
}

我没有在Table1类中使用类Table2的实例。

谢谢,
亚历

2 个答案:

答案 0 :(得分:3)

在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

没有连接,因为模型中没有关系。您只能通过cross product和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,以指定指向非主键的链接。

答案 1 :(得分:0)

非常感谢Stefan,最后我能够解决这个问题。

我会尝试使用另一个例子来模拟这个问题。希望这个可能对其他人有用。

问题:说我有两个表Employee和Project,项目表有两列'Lead'和'Manager',它们将存储Employee代码。我必须根据Manager和Lead的员工代码获取项目详细信息

这是我的问题的解决方案 员工映射文件。

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