web-dev-qa-db-fra.com

Syntaxe LINQ où la valeur de chaîne n'est ni nulle ni vide

J'essaie de faire une requête comme ça ...

query.Where(x => !string.IsNullOrEmpty(x.PropertyName));

mais ça échoue ...

donc pour l'instant j'ai mis en œuvre ce qui suit, qui fonctionne ...

query.Where(x => (x.PropertyName ?? string.Empty) != string.Empty);

existe-t-il une meilleure façon (plus native?) que LINQ gère cela?

MODIFIER

s'excuser! n'a pas inclus le fournisseur ... Ceci utilise LINQ to SQL

35
Jon Erickson

http://connect.Microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=367077

Énoncé du problème
Il est possible d'écrire LINQ to SQL qui obtient toutes les lignes qui ont une chaîne nulle ou vide dans un champ donné, mais il n'est pas possible d'utiliser string.IsNullOrEmpty pour le faire, même si de nombreuses autres méthodes de chaîne correspondent LINQ to SQL. Solution proposée Autorisez string.IsNullOrEmpty dans une clause where LINQ to SQL afin que ces deux requêtes aient le même résultat:

var fieldNullOrEmpty =
from item in db.SomeTable
where item.SomeField == null || item.SomeField.Equals(string.Empty)
select item;

var fieldNullOrEmpty2 =
from item in db.SomeTable
where string.IsNullOrEmpty(item.SomeField)
select item;

Autre lecture:
1. DevArt
2. Dervalp.com
3. StackOverflow Post

42
RSolberg

Cela n'échouera pas sur Linq2Objects, mais cela échouera pour Linq2SQL, donc je suppose que vous parlez du fournisseur SQL ou de quelque chose de similaire.

La raison tient à la façon dont le fournisseur SQL gère votre expression lambda. Il ne le prend pas comme une fonction Func<P,T>, Mais une expression Expression<Func<P,T>>. Il prend cette arborescence d'expressions et la traduit en une instruction SQL réelle, qu'elle envoie au serveur.

Le traducteur sait comment gérer les opérateurs de base, mais il ne sait pas comment gérer les méthodes sur les objets. Il ne sait pas que IsNullOrEmpty(x) se traduit par return x == null || x == string.empty. Cela doit être fait explicitement pour que la traduction en SQL ait lieu.

15
Brian Genisio

Cela fonctionnera très bien avec Linq to Objects. Cependant, certains fournisseurs LINQ ont des difficultés à exécuter des méthodes CLR dans le cadre de la requête. Cela est particulièrement vrai pour certains fournisseurs de bases de données.

Le problème est que les fournisseurs de bases de données essaient de déplacer et de compiler la requête LINQ en tant que requête de base de données, pour éviter de tirer tous les objets sur le câble. C'est une bonne chose, mais cela restreint parfois la flexibilité de vos prédicats.

Malheureusement, sans vérifier la documentation du fournisseur, il est difficile de toujours savoir exactement ce qui sera ou ne sera pas pris en charge directement dans le fournisseur. Il semble que votre fournisseur autorise les comparaisons, mais pas la vérification des chaînes. Je suppose que, dans votre cas, il s'agit probablement d'une approche aussi bonne que possible. (Ce n'est vraiment pas si différent de la vérification IsNullOrEmpty, à part la création de l'instance "string.Empty" pour comparaison, mais c'est mineur.)

2
Reed Copsey