2016-06-28 5 views
1

Ich habe diese Abfrage so weit zu passen:Der Versuch, ein Distinct() in eine relativ komplexe LINQ-Abfrage

var msg = ModelState.Values 
        .Where(x => x.Errors.Any()) 
        .Select(c => c.Errors.Select(d => d.ErrorMessage).Aggregate((e, f) => (e ?? "") + "<br/>" + f)) 
        .Aggregate((x, y) => (x ?? "") + "<br/>" + y); 

Das funktioniert perfekt, aber ich brauche die doppelten Fehlermeldungen auszufiltern. Ich habe versucht, sowohl GroupBy() und Distinct() an mehreren Stellen vor und nach dem Prädikat, das die ErrorMessage erhält, hinzuzufügen. Was vermisse ich?

Wenn ich das laufen, wie es ist, erhalte ich das folgende Ergebnis:

"Contact Email address invalid<br/>Contact Email address invalid" 

Jeder Wert Errormessage hier ist „Kontakt E-Mail-Adresse ungültig“. Dies sind die Duplikate, die ich herausfiltern möchte.

+1

Ist 'ErrorMessage' nur ein String oder ein Objekt? Wenn es; s nur eine Zeichenfolge dann 'c.Errors.Select (d => d.ErrorMessage) .Distinct(). Aggregate' sollte funktionieren –

+0

Ja, ErrorMessage ist eine Zeichenfolge, aber nein, das funktioniert leider nicht. Wenn ich das ausführe, erhalte ich folgendes: "Kontakt Email Adresse ungültig
Kontakt Email Adresse ungültig". Es sollte nur "Kontakt E-Mail-Adresse ungültig" sein. Ich werde das zum ursprünglichen Beitrag hinzufügen. – SomeDevTesting123

+0

Ich würde mir die Fehlermeldungen genau ansehen und sehen, ob es irgendwelche Leerzeichen oder andere Zeichen gibt, die die Prüfung "Distinct" ablehnen. –

Antwort

2

Kann ich eine Alternative vorschlagen?

Sie wollen Unter der Annahme, verschiedene Nachrichten, durch die Pause-Tag getrennt:

var items = ModelState.Values 
    .SelectMany(c => c.Errors.Select(d => d.ErrorMessage)) 
    .Distinct() 
    .ToArray(); 

string msg = string.Join("<br/>", items); 
+0

Perfekt, danke. – SomeDevTesting123

2

Das Problem ist, dass man zwei Stellen haben produzieren Werte. Betrachten Sie den folgenden Fall:

Value Errors 
1.  "Bad username", "Contact Email address invalid" 
2.  "Contact Email address invalid" 

Auch wenn Sie Distinct beide Select Anrufe hinzufügen, wird es nicht tun, was Sie wollen, wie wird Contact Email address invalid verglichen werden, gefunden werden nicht gleich zu sein, und wird aggregiert in Bad username<br/>Contact Email address invalid<br/>Contact Email address invalid, die, wie ich annehme, nicht das ist, was Sie wollen.

Stattdessen sollten Sie zuerst die verschachtelten Fehlerlisten reduzieren. Dies ist die Aufgabe von SelectMany. Um Ihre Liste abflachen, müssen Sie genau das tun:

var errorMessages = ModelState.Values 
       .Where(x => x.Errors.Any()) 
       .SelectMany(c => c.Errors.Select(d => d.ErrorMessage)) 

Jetzt errorMessages ist eine Liste von jeder Fehlermeldung von jedem Value. (Beachten Sie, dass die Where ist wahrscheinlich nicht benötigte. Select oder SelectMany auf eine leere Sequenz ist eine no-op)

Jetzt gibt es die zweite Ausgabe:

Es ist fast immer eine schlechte Praxis + zu verwenden, um mit Zeichenketten in C#, aufgrund der Unveränderlichkeit von string. Stattdessen möchten Sie string.Join, string.Format oder StringBuilder verwenden abhängig davon, ob Ihre Eingabe eine Sequenz, mehrere Variablen oder längere Strings ist. In diesem Fall wird ein Array haben, so ist string.Join das Werkzeug der Wahl:

var msg = string.Join("<br/>", errorMessages.Distinct()) 
+0

So sollten alle Stack Overflow-Antworten aussehen. Nicht nur "hier, nimm meinen Code". – Neolisk

+0

@Neolisk jetzt muss ich nur hoffen, dass ich keinen dummen Fehler gemacht habe ... – RoadieRich

+0

Ihre Erklärung sollte Rolle einer Prüfsumme spielen. :) – Neolisk