web-dev-qa-db-fra.com

Linq où la colonne == (référence nulle) n'est pas la même que la colonne == null

Je suis tombé sur un problème assez étrange avec linq-to-sql. Dans l'exemple suivant,

var survey = (from s in dbContext.crmc_Surveys
                                   where (s.crmc_Retail_Trade_Id == tradeId) && (s.State_.Equals(state))
                                   select s).First();

Si tradeId est null, il ne se comporte pas comme si j'avais spécifié null spécifiquement comme ceci à la place,

var survey = (from s in dbContext.crmc_Surveys
                                   where (s.crmc_Retail_Trade_Id == null) && (s.State_.Equals(state))
                                   select s).First();

Quel est mon comportement souhaité. En fait, il ne renvoie rien sauf si les deux valeurs sont non nulles. Je ne peux pas comprendre comment accomplir ce court de plusieurs requêtes linq différentes. Des idées?

26
Boog

Remplacez where (s.crmc_Retail_Trade_Id == tradeId) par

where (s.crmc_Retail_Trade_Id == tradeId || 
      (tradeId == null && s.crmc_Retail_Trade_Id == null))

Modifier - basé sur cet article par Brant Lamborn, il semble que ce qui suit ferait ce que vous voulez:

where (object.Equals(s.crmc_Retail_Trade_Id, tradeId))

La page Null Semantics (LINQ to SQL) MSDN renvoie à des informations intéressantes:

LINQ to SQL n'impose pas de sémantique de comparaison de rien null C # ou Visual Basic à SQL. Les opérateurs de comparaison sont traduits syntaxiquement dans leurs équivalents SQL. La sémantique reflète la sémantique SQL définie par le serveur ou les paramètres de connexion. Deux valeurs nulles sont considérées comme inégales dans les paramètres par défaut de SQL Server (bien que vous puissiez modifier les paramètres pour modifier la sémantique). Quoi qu'il en soit, LINQ to SQL ne prend pas en compte les paramètres du serveur dans la traduction des requêtes.

Une comparaison avec le littéral null (rien) est traduite dans la version SQL appropriée (est null ou n'est pas null).

La valeur de null (rien) dans le classement est définie par SQL Server; LINQ to SQL ne modifie pas le classement.

32
jball

Je ne suis pas sûr sur celui-ci, mais je soupçonne que lorsque linq-to-sql traduit cela en une chaîne de requête sql, vous obtenez une expression légèrement différente spécifiant null directement de telle sorte qu'à un moment donné, vous finissez par comparer NULL à lui-même, et NULL = NULL est défini comme faux.

2
Joel Coehoorn

Une autre option pour résoudre ce problème, car j'ai également rencontré ce problème.

where (tradeId == null ? s.crmc_Retail_Trade_Id == null : s.crmc_Retail_Trade_Id == tradeId)
2
Greg Klaus

Je ne connais pas Linq, cependant en général:

NULL représente une valeur manquante, inconnue ou indéfinie. À strictement parler, une variable ne peut pas être égale à NULL; les langages de bas niveau qui fournissent cette construction le font généralement par commodité car il n'y a pas d'alternative facile - à un niveau supérieur, il est généralement préférable de s'appuyer sur ISNULL, defined, ou sur les fonctionnalités de votre fournitures linguistiques.

Une variable non définie n'est pas égale à une autre variable non définie (et la même chose s'applique à NULL == NULL). Joe Celko a un bon exemple d'écriture d'une requête pour trouver toutes les personnes dont la couleur des cheveux correspond à la couleur du véhicule qu'ils conduisent. Cette requête doit-elle correspondre à un homme chauve qui marche partout?

1
Duncan

Il est préférable de créer sp à cet effet car linq effectuera l'itération nécessaire pour votre assistance si vous utilisez linq.

var c = lstQ_Buffer.Where(q => (((semesterId == 0 || semesterId == null ? q.fkSemesterId == null : q.fkSemesterId == semesterId) && (subjectSpecialtyId == 0 || subjectSpecialtyId == null ? q.fkSubSpecialtyId == null : q.fkSubSpecialtyId == subSpecialtyId) && (subTopicId == 0 || subTopicId == null ? q.fkSubTopicId == null : q.fkSubTopicId == subTopicId)) && (q.fkProgramId == programId && q.fkYearId == yearId && q.fkCourse_ModuleId == courseModuleId && q.fkSubject_SpecialtyId == subjectSpecialtyId && q.fkTopicId == topicId && q.fkDifficultyLevelId == diffucultyLevelId))).ToList();
0
Ubaid Ur Rehman