Le || (ou) l'Exploitant de Linq avec C#
Je suis à l'aide de linq pour filtrer une sélection de MessageItems. La méthode que j'ai écrit accepte un tas de paramètres qui peuvent être null. Si ils sont nuls, les critères pour le fichier doit être ignorée. Si elle n'est pas nulle, l'utiliser pour filtrer les résultats.
C'est ma compréhension que lorsqu'on fait un || opération est C#, si la première expression est vraie, la seconde expression ne doit pas être évaluée.
par exemple
if(ExpressionOne() || ExpressionTwo())
{
//only ExpressionOne was evaluated because it was true
}
maintenant, linq, je vais essayer ceci:
var messages = (from msg in dc.MessageItems
where String.IsNullOrEmpty(fromname) || (!String.IsNullOrEmpty(fromname) && msg.FromName.ToLower().Contains(fromname.ToLower()))
select msg);
J'aurais pensé que ce serait son, parce que String.IsNullOrEmpty(fromname)
serait égal à true, et la deuxième partie de la || de ne pas se faire rouler.
Toutefois, il ne s'exécuter, et la deuxième partie
msg.FromName.ToLower().Contains(fromname.ToLower()))
lève une exception de type référence nulle (car fromname
est nul)!! - Je reçois un classique "la référence d'Objet n'est pas définie à une instance d'un objet" l'exception".
Toute aide?
Ah cool. Ok Lucas, donc je suis en utilisant Linq to SQL. Je pense que vous savez vraiment ce que je suis sur le sujet ici. Donc, vous dites dans Linq to SQL, vous ne devriez pas attendre que cela fonctionne? Comment dois-je tirer cette off dans Linq to SQL? Je veux juste dire: Si le paramètre passé est nulle, puis obtenir l'enregistrement, indépendamment d'un match, si ce n'est pas null, alors, de s'assurer que chaque enregistrement retourné correspond à l'passées en paramètre. Merci beaucoup!
Ev, si c'est linq to sql puis de court-circuit de l'évaluation tout simplement n'est pas quelque chose que vous pouvez compter sur arrêt complet
Bon, c'est cool @ShuggyCoUk. J'apprécie l'entrée! Vous voyez ce que je suis en train de faire ici? On dirait que je suis totalement en manque de quelque chose!Je sais que ce serait le travail en SQL et je sais travailler en C#, donc il doit y avoir une sorte d'équivalent dans Linq to SQL. Suis-je le droit? Donc, tout ce que je veux dire c'est que, dans ce cas particulier où la clause, soit toutes les lignes, si le paramètre fromname est null. Si nomsource n'est PAS NULLE, de sorte que nous correspondre au paramètre. M'attraper? Merci encore pour votre aide mate
Vous n'êtes pas à l'aide de LINQ to SQL, parce que (1) la Méthode 'Boolean IsNullOrEmpty(Système d'.String)' a aucune prise en charge de la traduction de SQL et (2) vous ne seriez pas obtenir le NullReferenceException (il se produirait uniquement côté client, pas sur la DB).
OriginalL'auteur Ev. | 2009-04-21
Vous devez vous connecter pour publier un commentaire.
Avoir une lecture de cette documentation qui explique comment linq et c# est ce que l'expérience d'une déconnexion.
Depuis des expressions Linq devrait être réduit à quelque chose d'autre que la plaine de méthodes que vous pouvez trouver que ce code des pauses si plus tard il est utilisé dans certains pays non Linq to Objects contexte.
Que dit
Est mal formé, car il devrait vraiment être
qui la rend agréable et clair que vous êtes en s'appuyant sur le msg et msg.FromName à la fois d'être non null.
Pour rendre votre vie plus facile en c# vous pouvez ajouter la chaîne suivante de la méthode d'extension
Alors utiliser:
Cependant, ce n'est pas le problème. Le problème est que le Linq to SQL aspects du système essayez d'utiliser la
fromname
valeur de construire le requête qui est envoyé au serveur.Depuis
fromname
est une variable le mécanisme de traduction s'éteint et fait ce qui est demandé (la production d'une plus faible représentation defromname
même si elle est nulle, ce qui déclenche l'exception).dans ce cas, vous pouvez faire ce que vous avez déjà découvert: garder la requête est aussi, mais assurez-vous que vous pouvez toujours créer un non-nulle de fromname de la valeur avec le comportement souhaité, même si elle est nulle.
Peut-être mieux serait:
Ce n'est pas si grand qu'il la requête contenue d'autres contraintes, et donc d'impliquer plus de duplication, mais pour la requête simple fait devrait entraîner plus lisible et maintenable code. C'est une douleur si vous êtes en s'appuyant sur les types anonymes, mais j'espère que ce n'est pas un problème pour vous.
votre impression que (a == null || utilisation(a)) est légitime est mal dans Linq simple et clair désolé. Avez-vous essayé ma méthode d'extension avec la revisesed clause where?
depuis les choses comme sql moteurs ne sont pas garantis à faire le tri de court-circuit d'évaluation (sans avoir recours à de merde des choses comme des cas), le système Linq ne garantit pas que ce qui se passe (d'où le document à ce sujet). Vous n'avez pas à écrire l'extension - c'est déjà là dans la réponse.
Ah ok. J'ai pris vous étiez en le tirant les données de filtrage puis après. Ce n'est pas d'aller travailler. Je vais la modifier en conséquence.
Quel que soit votre solution est a fondamentalement fournir une valeur non nulle pour le Contient ou éviter tout ensemble (comme la mienne) désolé
OriginalL'auteur ShuggyCoUk
D'accord. J'ai trouvé Un solution.
J'ai changé la ligne incriminée:
Il fonctionne, mais il se sent comme un hack. Je suis sûr que si la première expression est vraie, la seconde devrait pas évaluée.
Serait génial si quelqu'un pouvait confirmer ou d'infirmer cette pour moi...
Ou si quelqu'un a une meilleure solution, s'il vous plaît laissez-moi savoir!!!
OriginalL'auteur Ev.
Si vous êtes à l'aide de LINQ to SQL, vous ne peut pas s'attendre à la même C# court-circuit comportement de SQL Server. Voir cette question sur court-circuit
WHERE
clauses (ou son absence) dans SQL Server.Aussi, comme je l'ai mentionné dans un commentaire, je ne crois pas que vous êtes l'obtention de cette exception dans LINQ to SQL, car:
String.IsNullOrEmpty(String)
n'a pas pris en charge la traduction de SQL, de sorte que vous ne pouvez pas l'utiliser dans LINQ to SQL.Êtes-vous sûr de ne pas passer par LINQ to Objects quelque part? Êtes-vous en faveur ToList() ou ToArray() sur la source ou référence à elle comme un IEnumerable<T> avant l'exécution de cette requête?
Mise à jour: Après lecture de vos commentaires, j'ai testé à nouveau et réalisé certaines choses. Je me suis trompé sur vous pas l'utilisation de LINQ to SQL. Vous ne recevaient pas les
"String.IsNullOrEmpty(String) has no supported translation to SQL"
exception parce queIsNullOrEmpty()
est appelé sur une variable locale, pas une colonne SQL, donc il est exécutant côté client, même si vous êtes en utilisant LINQ to SQL (pas de LINQ to Objects). Depuis qu'il est en cours d'exécution côté client, vous peut obtenir unNullReferenceException
sur cet appel de méthode, car il n'est pas traduit à SQL, où vous ne pouvez pas obtenir unNullReferenceException
.Une façon de rendre votre solution semble moins hacky est résoudre
fromname
'"null-ness" à l'extérieur de la requête:Noter que ce ne sera pas toujours être traduit à quelque chose comme (à l'aide de vos commentaires à titre d'exemple):
Sa traduction sera décidé au moment de l'exécution, selon que
fromname
est null ou pas. Si elle est nulle, il sera de traduire sansWHERE
clause. Si elle n'est pas null, il sera de traduire avec un simple "WHERE @theValue = theValue
", sans nul vérifier en T-SQL.Donc en fin de compte, la question de savoir s'il court-circuit dans SQL ou non n'est pas pertinent dans ce cas parce que le LINQ to SQL runtime émettent différentes requêtes T-SQL si
fromname
est null ou pas. Dans un sens, elle est court-circuitée côté client avant d'interroger la base de données.SÉLECTIONNEZ * à PARTIR de tblSomeTable OÙ @theValue EST NULL OU @theValue = theValue
Donc, si vous avez des idées, ce serait sympa!
merci, vos commentaires m'a fait comprendre que j'ai fait une erreur. j'ai mis à jour ma réponse.
OriginalL'auteur Lucas
Êtes-vous sûr que c'est "fromname" c'est nul et n'est pas 'msg.FromName " c'est nul?
Alors juste pour préciser - c'est fromname qui est nul - pas de msg.FromName. D'autres idées?
Ce que @ShuggyCoUk dit. Quel est le type de dc.MessageItems? A-t-elle une fantaisie fournisseur LINQ?
Salut Brian. C'est ma propre classe. Je suis à l'aide de Linq to SQL, donc c'est un objet, qui représente essentiellement un tableau. Les membres sont des choses comme msg.FromName, msg.E-mail, msg.Emplacement, msg.le Texte du message - pas de folles fournisseur. Donc, dc.MessageItems, est une collection de MessageItem en gros, j'ai juste besoin de savoir pourquoi la deuxième partie de la ou operatoinis en cours d'évaluation, même si la première expression est "Vrai"! 🙂 Merci pour l'aide!
OriginalL'auteur Brian
Comme Brian dit, je regarde si le msg.FromName est null, avant de faire la ToLower().Contient(fromname.ToLower()))
OriginalL'auteur Nordes
Il est exact que le second conditionnelle ne devrait pas évaluée en tant que vous utilisez le court-circuit comparitors (voir Quelles sont les bonnes pratiques concernant C# court-circuit d'évaluation?), cependant j'avais soupçonner que le Linq peut essayer d'optimiser votre requête avant de l'exécuter et de le faire pourrait modifier l'ordre d'exécution.
Enveloppant le tout entre parenthèses aussi, pour moi, rend pour une meilleure instruction que l'ensemble du " où " la condition est contenue dans le parenthases.
Devrait l'ai mentionné, j'ai essayé beaucoup de différentes parenthases options!
OriginalL'auteur Lazarus