2010-11-22 3 views
1

Je suis nouveau à Nhibernate, j'essaie d'utiliser nhibernate dans un projet et je voulais convertir la requête sql suivante à Nhibernate HQL? Cette requête est-elle possible dans Nhibernate HQL/ICriteria?NHinerbate Query problem - Rejoindre une requête avec des non-primarykeys

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 

ce que j'ai essayé et je reçois failed.I une exception prévue pour chemin rejoindre!

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

Toute aide serait appréciée.

Édition 1: Ajout de classes que j'utilise.

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

Je n'ai pas utilisé instance de la classe Tableau2 dans la classe Table1.

Merci,
Alex

+0

Qu'est-ce que «a» et «e» dans votre requête HQL? –

+0

bien c'était erreur (il était de mon code de production, il a été retiré maintenant) – wizzardz

Répondre

0

Merci beaucoup Stefan, enfin je suis capable de résoudre ce problème.

Je vais essayer d'émuler le problème en utilisant un autre exemple. J'espère que celui-ci pourrait être utile à quelqu'un d'autre.Problème: disons que j'ai deux tables Employé et Projet, la table de projet a deux colonnes 'Lead' et 'Manager' qui vont stocker le code Employé. J'ai dû obtenir les détails du projet basé sur le code employé du Manager et Conduire.

Voici la solution à mon problème.
Fichier de mappage d'employés.

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

fichier de mappage du projet:

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

d'employés:

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

Classe projet:

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

} 

J'ai dû obtenir les détails du projet en fonction du code employé de 'ProjectLead' et 'ProjectManager', et c'est la requête HQL que j'ai utilisée.

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

En HQL, vous ne joignez pas "tables". Vous démarrez la requête sur la première classe et accédez aux propriétés.

par exemple:

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

class B 
{ 
} 

hQPD:

SELECT a FROM A a join MyB 

myb est un nom de propriété.

Pour vous montrer la requête réelle pour votre cas, j'ai besoin de connaître les classes pour lesquelles vous voulez écrire la requête.

Il peut ressembler à ceci:

SELECT t1 
FROM T1 t1 
    join MyT2 t2 

Modifier:

La requête à vos classes ressemblerait à ceci:

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

Il n'y a rejoindre pas , parce qu'il n'y a pas de relation dans le modèle. Vous ne pouvez le joindre que par produit cross et clause where.

Vous ne bénéficiez pas beaucoup de NH lorsque vous ne travaillez pas avec un modèle de classe utile. Utile signifie que vous pouvez naviguer dans le modèle sans accéder à la base de données tout le temps. Lorsque vous écrivez simplement des classes qui ressemblent à des tables de base de données, vous n'en bénéficierez pas beaucoup.

Vos cours pourraient ressembler à ceci:

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

Ensuite, vous associez comme many-to-one en utilisant property-ref pour spécifier un lien vers une clé non primaire.

+0

Salut Stefan, merci pour la réponse. J'ai ajouté un exemple de modèle des classes que j'ai utilisées. – wizzardz

+0

Est-il nécessaire que nous ayons besoin d'une instance de classe B dans la classe A même s'il n'y a pas de relation physique entre le tableau A et la table B? – wizzardz

+0

Même si un FK contraint n'existe pas, vous devrez toujours mapper la propriété Id2 à la classe Table2 au lieu du Guid que vous présentez dans votre mapping. L'idée derrière NH est la seule chose que vous connaissez est le domaine et dans HQL vous traversez expressivement le graphique et NH traduit cela en SQL réel. Donc, si la propriété Id2 de Table1 représente l'Id de Table2 et que vous voulez traverser Table2 dans votre domaine, vous devrez mapper cette propriété comme un objet de type Table2 – Jaguar