2009-05-07 10 views
4

J'ai 2 classes nommées Order et Orderrow. J'utilise NHibernate pour obtenir une jointure.La création de NHibernate SQL provoque une erreur

Lors de l'exécution NUnit pour tester la requête, je suis un ADOException:

Logica.NHibernate.Tests.NHibernateTest.SelectAllOrdersFromSupplierNamedKnorrTest: 
NHibernate.ADOException : could not execute query 
[ SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM Order this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId ] 
[SQL: SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM Order this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId] 
    ----> System.Data.SqlClient.SqlException : Incorrect syntax near the keyword 'Order'. 

Lors de l'analyse SQL qui a été créé par NHibernate, je remarque que la classe Ordre corrompt l'instruction SQL, parce que ORDER BY est un mot clé interne dans SQL.

C'est le SQL créé en NHibernate:

SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM Order this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId 

Je l'ai changeai dans SQL Server 2008 Management Studio comme ceci:

SELECT this_.OrderId as OrderId1_1_, this_.CreatedAt as CreatedAt1_1_, this_.ShippedAt as ShippedAt1_1_, this_.ContactId as ContactId1_1_, customer2_.ContactId as ContactId0_0_, customer2_.LastName as LastName0_0_, customer2_.Initials as Initials0_0_, customer2_.Address as Address0_0_, customer2_.City as City0_0_, customer2_.Country as Country0_0_ FROM [Order] this_ inner join Contact customer2_ on this_.ContactId=customer2_.ContactId` 

J'ai ajouté entre parenthèses à l'ordre du nom de la table (comme celui-ci: [Ordre]) et il est fixé. Mais comment puis-je corriger cela dans NHibernate? Existe-t-il une instruction de fichier XML de mappage pour que cela soit fait?

(en utilisant VS2008 SP1, SQL Server 2008 SP1, NHibernate 2.0.1 GA)

Répondre

6

Je pense que si vous mettez les guillemets (« [ » et « ] » dans SQL Server, ou quel que soit votre citation DB prend en charge) dans votre fichier de mappage, Hibernate citer les noms des objets lorsque il génère des requêtes.

(poster Peut-être votre fichier de mappage, afin que nous puissions jeter un coup d'oeil)

+0

Juste une note: Je sais que [et] ne sont pas des standards SQL, mais ce sont les citations par défaut utilisées par le serveur SQL. –

+0

J'ai ajouté table = "[Order]" et ça marche! –

+3

Dans NH, le backtick est effectivement utilisé pour cela, voir la réponse d'Anton. C'est la syntaxe NH indépendante de la base de données. –

6

Voir this, section "5.3. SQL des identificateurs entre guillemets". Yoo essentiellement besoin ceci:

<class name="Order" table="`Order`"> 
+0

Le '' ne fonctionne pas, j'obtiens une erreur de syntaxe invalide –

+0

Vous avez ajouté un mauvais caractère. Vous avez besoin d'un "backtick" (terminologie de NHibernate docs), qui est juste sous la touche de tabulation, pas l'apostrophe. –

+1

Hmmm ... il est juste * ci-dessus * la touche Tab :) –

5

En Fluent NHibernate, ajoutez

.Column("`Order`"); 

à votre application pour corriger cette erreur.

+0

C'est exactement ce dont j'avais besoin pour que ma propriété/colonne "Order" fonctionne. J'ai eu classe avec la propriété Order et seulement après avoir ajouté ce mappage personnalisé, il a commencé à fonctionner. –

0

Lors de l'utilisation des conventions, vous pouvez ajouter ce qui suit:

public class TableNameConvention 
    : IClassConvention, IClassConventionAcceptance 
{ 
    public void Accept(IAcceptanceCriteria<IClassInspector> criteria) 
    { 
     criteria.Expect(x => Check(x)); 
    } 

    private bool Check(IClassInspector x) 
    { 
     return String.IsNullOrWhiteSpace(x.TableName) || x.TableName.Equals("`{0}`".Args(x.EntityType.Name)); 
    } 

    public void Apply(IClassInstance instance) 
    { 
     instance.Table("`" + instance.EntityType.Name + "`"); 
    } 
} 

pour résoudre le problème avec les noms de tables réservées et pour les noms de colonnes réservées (par exemple, « From »), on peut utiliser les éléments suivants:

public class ColumnNameConvention : IPropertyConvention, IPropertyConventionAcceptance 
{ 
    public void Apply(IPropertyInstance instance) 
    { 
     instance.Column("`" + instance.Property.Name + "`"); 
    } 

    public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria) 
    { 
     criteria.Expect(c => Check(c)); 
    } 

    private bool Check(IPropertyInspector inspector) 
    { 
     //walkaround: 
     //this convention causes problems with Components - creates columns like Issue`Id` so we apply it only to entities 

     var type = inspector.EntityType; 
     if (!(type.IsSubclassOf(typeof (Entity)) || type.IsSubclassOf(typeof (GlossaryEntity)))) 
     { 
      return false; 
     } 

     return true; 
    } 
} 
Questions connexes