2017-05-05 1 views
0

Ich habe ein Problem, wo ich Ergebnisse zurückgeben soll, wo etwas stimmt und ich einen Fehler erhalte, wenn eine der Eigenschaften, die ich versuche, ist null.Null Wert in Linq Where-Klausel

if (!string.IsNullOrEmpty(searchString)) 
    { 
     Infos = Infos.Where(
      x => 
      x.FirstName.ToLower().Contains(searchString) || 
      x.LastName.ToLower().Contains(searchString) || 
      x.ContractNum.ToLower().Contains(searchString) || 
      x.VIN.ToLower().Contains(searchString) || 
      x.Claim.InitiatedBy.ToLower().Contains(searchString) 
     ).ToList(); 
    } 

Wenn ContractNum oder VIN zum Beispiel null sind, dann wirft es einen Fehler. Ich bin mir nicht sicher, wie man innerhalb einer linq-Abfrage überprüft, ob einer von diesen null ist.

+1

LINQ Ausdrücke sind nicht anders als normale boolesche Ausdrücke, so dass die Überprüfung auf Null ist genau das gleiche. –

Antwort

1

die Eigenschaft Überprüfung null oder leer ist, bevor es es ist die einzige Möglichkeit, zu vergleichen Ich weiß

if (!string.IsNullOrEmpty(searchString)) 
     { 
      Infos = Infos.Where(
       x => 
       (!String.IsNullOrEmpty(x.FirstName) && x.FirstName.ToLowerInvariant().Contains(searchString)) || 
       (!String.IsNullOrEmpty(x.LastName) && x.LastName.ToLowerInvariant().Contains(searchString)) || 
       (!String.IsNullOrEmpty(x.ContractNum) && x.ContractNum.ToLowerInvariant().Contains(searchString)) || 
       (!String.IsNullOrEmpty(x.VIN) && x.VIN.ToLowerInvariant().Contains(searchString)) || 
       (x.Claim != null && !String.IsNullOrEmpty(x.Claim.InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant().Contains(searchString)) 
      ).ToList(); 
     } 

EXTRA: Ich habe eine Überprüfung der Claim Eigenschaft, um sicherzustellen, es ist nicht null beim Betrachten InitiatedBy

EXTRA 2: Mit der integrierten Funktion IsNullOrEmpty zu vergleichen str ing an "" und null so ist der Code klarer.

Extra 3: Verwendet von ToLowerInvariant (https://msdn.microsoft.com/en-us/library/system.string.tolowerinvariant(v=vs.110).aspx), so dass die Senkwirkung unabhängig von der Kultur gleich wirkt.

+0

Ich mag diese Antwort am besten für ihre Vollständigkeit, sogar obwohl ich mich nicht wirklich für Kulturen interessiere. Die einzige Sache ist, dass Reshaper vorschlägt, dass Sie die letzten beiden sequentiellen Überprüfungen zusammenfassen in: '(! String.IsNullOrEmpty (x.Claim? .InitiatedBy) && x.Claim.InitiatedBy.ToLowerInvariant(). Enthält (searchString))' –

+1

I stimme hier mit dem allmächtigen Resharper überein. – Muffun

+0

Ich würde wahrscheinlich eine Methode extrahieren, um die Aufrufe von 'string.IsNullOrEmpty()' und '.ToLowerInvariant() nicht zu wiederholen. Enthält()' und um den Fall abzudecken, in dem sich die Testkriterien ändern. Abhängig von der Domäne könnte man sogar entscheiden, dass das Objekt selbst diese Methode verfügbar macht, wenn dies geeignet ist, mögliche Duplizierungen weiter zu reduzieren. –

5

können Sie explizite null Prüfungen hinzufügen:

Infos = Infos.Where(
     x => 
     (x.FirstName != null && x.FirstName.ToLower().Contains(searchString)) || 
     (x.LastName != null && x.LastName.ToLower().Contains(searchString)) || 
     (x.ContractNum != null && x.ContractNum.ToLower().Contains(searchString)) || 
     (x.VIN != null   && x.VIN.ToLower().Contains(searchString)) || 
     (x.Claim != null  && x.Claim.InitiatedBy != null && x.Claim.InitiatedBy.ToLower().Contains(searchString)) 
    ).ToList(); 
+0

Sie könnten so etwas versuchen. Es erlaubt sowohl null als auch nicht null. (string.Equals (x.ContractNum, String.Leer) || x.ContractNum.Trim(). Enthält ("searchString")) –

+0

@JeanB Sicher, es gibt ein paar verschiedene Möglichkeiten, es anzugehen. Fühlen Sie sich frei, eine andere Antwort hinzuzufügen. –

+0

Mein Verstand wurde in letzter Zeit wirklich überbeansprucht und ich bin mir nicht sicher warum ich das einfach nicht gemacht habe/erinnere mich wie ich das gemacht habe. Ich habe versucht zu setzen? überall und es gibt mir immer wieder Fehler. Solch eine einfache Lösung. –

1

Sie ?? es mit einem akzeptablen Wert zu ersetzen, verwenden könnte.

(x.ContractNum??"").ToLower() 
+2

Bitte nicht. Tu das nicht. Führen Sie nur eine regelmäßige Nullprüfung durch. –

+1

Was wäre der Unterschied? – ThatChris

+1

Nutzlose 'ToLower()' und nachfolgende Aufrufe. –

1

würde ich den Null-bedingten Operator ?, dies jedoch wird, kehrt eine Nullable-bool? so müssen Sie, dass in geeigneter Weise zu handhaben.

Einige Beispiele dafür, wie dies zu tun:

x?.FirstName?.ToLower().Contains(searchString) == true; 
x?.FirstName?.ToLower().Contains(searchString) ?? false; 
+1

Die letzte Option ist am besten IMHO. –

+0

Dies funktioniert nur für C# 6+. Aber das ist auch eine gute Option :) –

+2

@PatrickHofman Normalerweise bevorzuge ich die letzte auch als '== true' und entspricht liest mir falsch. – TheLethalCoder

2

Sie haben mehrere Optionen, zuerst ist eine explizite Prüfung gegen null und die andere Option zu tun ist, Null Ausbreitungs Operator zu verwenden.

x.FirstName != null && x.FirstName.ToLower().Contains(searchString) 

oder

x.FirstName?.ToLower()?.Contains(searchString) == true 

Aber ich würde Sie Verwendung IndexOf statt Contains für Fall unempfindlich Vergleich vorschlagen.

so etwas wie:

x.FirstName?.IndexOf(searchString, StringComparison.CurrentCultureIgnoreCase) > 0) 
+0

@ TimSchmelter, danke Tim. – Habib

+0

Was wäre der Vorteil Ihres Vorschlags, IndexOf zu verwenden? –

+0

@BarryFranklin, http://haacked.com/archive/2012/07/05/turkish-i-problem-and-why-you-should-care.aspx/ – Habib

1

Ein alternatives Verfahren der Vergleichslogik in einem Ort zu halten eine Unter Sammlung der Eigenschaften zu verwenden und auf die überprüfen:

Infos = Infos.Where(i=> 
    new[] {i.FirstName,i.LastName,i.ContractNum /*etc*/} 
    .Any(w=> w?.ToLower().Contains(searchString) ?? false)) 
    .ToList(); 

(Es wird alle Eigenschaften nicht gelesen, aber das soll nicht viel kosten Leistung und erhält viel Wartbarkeit)

+0

Der Aufbau eines neuen Arrays ist sinnlos, verliert meiner Meinung nach die Lesbarkeit und dauert wahrscheinlich länger. Ich glaube auch, dass es "Select" und nicht "Where" sein sollte. – TheLethalCoder

+0

@TheLethalCoder Lesbarkeit kann strittig sein, aber anstatt die Logik für jede einzelne Eigenschaft zu wiederholen, bleibt sie an einem Ort. Imho erhöht die Lesbarkeit. (und stellt sicher, dass man '' '' '' für eine Eigenschaft nicht vergessen kann). Auf jeden Fall ist 'Where' korrekt: Das Array wird nur für' Any' verwendet und es werden Kurzschlüsse bei einer Übereinstimmung erzeugt. –

+0

In Bezug auf die Leistung: ja , das ist in Millisekunden auf größeren Listen schwerer, aber wenn das ein Problem ist, würde ich eine Art Iterator erstellen und die Prüflogik an einem Ort behalten. –