2010-09-28 10 views
0

je la requête suivante dans HQL:résultats incohérents entre NHibernate requêtes et résultats attendus

public IEnumerable<Player> PlayersNotInTeam(Team team) 
{ 
    return Session.CreateQuery("from Player p where p.Sex = :teamSex and p.Visible and p.Id not in (select pit.Player from PlayerInTeam as pit join pit.Roster as roster join roster.Team as team where team = :teamId)") 
     .SetParameter("teamId", team.Id) 
     .SetParameter("teamSex", team.Sex) 
     .Enumerable<Player>(); 
} 

Quand je lance cette requête avec NHibernate, il retournera 2 lignes.

Si je lance le script SQL généré par NH dans mon navigateur de base de données (SQLite Explorer):

select player0_.Id as Id26_, player0_.Sex as Sex26_, player0_.FirstName as FirstName26_, player0_.LastName as LastName26_, player0_.DefaultNumber as DefaultN5_26_, player0_.Visible as Visible26_, player0_.DefaultPosition_id as DefaultP7_26_ 
    from Players player0_ 
    where player0_.Sex='Male' 
     and player0_.Visible=1 
     and (player0_.Id not in 
      (select playerinte1_.Player_id 
      from "PlayerInTeam" playerinte1_ 
      inner join "Roster" roster2_ on playerinte1_.Roster_id=roster2_.Id 
      inner join Teams team3_ on roster2_.Team_id=team3_.Id, 
      Players player4_ 
      where playerinte1_.Player_id=player4_.Id 
       and team3_.Id=2)); 

J'ai 3 lignes, ce qui est ce que je devrais avoir.

Pourquoi mes résultats sont-ils différents?

Merci à l'avance

Mike

Répondre

0

J'ai remarqué que parfois le SQL est connecté pas exactement le même que celui qui est vraiment utilisé contre la base de données. La dernière fois que j'ai eu ce problème, il y avait un problème avec la valeur Id, par exemple, où le SQL généré a quelque chose comme and team3_.Id=2, le SQL utilisé était en fait and team3_.Id='2 ' (ou peut-être, player_0.Sex='Male '), qui échouerait toujours.

Je vous suggère d'essayer HQL:

string hql = @"from Player p where p.Sex = 'Male' 
       and p.Visible and p.Id not in 
       (select pit.Player from PlayerInTeam as pit join pit.Roster as roster join roster.Team as team where team = 2)"; 
return Session.CreateQuery(hql).Enumerable<Player>(); 

Si cela fonctionne, vous devez vérifier si vos valeurs ont des espaces blancs de rechange en eux.

+0

Malheureusement cela ne fonctionne pas non plus:/J'ai essayé plusieurs combinaisons de guillemets, sans, mais je n'obtiens pas les résultats corrects ... – Mike

+0

Mike, pourriez-vous essayer d'utiliser un LIKE% Male% au lieu d'un '='? Juste pour s'assurer que NHibernate n'est pas trop intelligent à propos des choses? – rebelliard

+0

Le sexe est une énumération. J'ai ajouté une convention dans FluentNhibernate qui stocke la valeur de l'enum au lieu du nom. J'ai donc Male = 0 et Female = 1. Mais j'ai toujours les mêmes résultats. Le problème n'est pas là, car le joueur oublié a le même sexe que les 2 joueurs retournés ... – Mike

0

J'ai changé ma requête comme ceci:

return Session.CreateQuery("from Player p where p.Sex = :teamSex and p.Visible and not exists (from PlayerInTeam pit where pit.Player = p and pit.Roster.Team = :teamId)") 
      .SetParameter("teamId", team.Id) 
      .SetParameter("teamSex", team.Sex) 
      .Enumerable<Player>(); 

Et ça marche maintenant. J'ai eu l'idée d'utiliser "non existe" après avoir changé mes mappings pour essayer d'utiliser LINQ, ce qui m'a donné l'indice. Si vous demandez pourquoi je ne garde pas LINQ, c'est parce que je cache actuellement les relations entre mes entités comme des champs privés, pour forcer les utilisateurs des entités à utiliser les fonctions d'aide qui les associent. Mais la mauvaise chose est que dans la plupart des cas, cela m'interdit d'utiliser LINQ dans mes dépôts. Mais je me demande si cela ne serait pas mieux de "cacher" mes relations et de les exposer comme des propriétés publiques, mais de garder mes fonctions d'aide. Cela me permettrait d'utiliser LINQ dans mes requêtes.

Que faites-vous dans vos applications en utilisant NH? Pensez-vous que ce serait un compromis acceptable pour maintenir des mappages et des requêtes faciles (avec l'utilisation de LINQ), mais avec le coût de certains abus potentiels des entités si l'utilisateur n'utilise pas les fonctions d'aide qui garde les relations?

Questions connexes