Ich habe diese Frage:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
Was wird passieren, maxShoeSize
wenn Unternehmen 8 überhaupt keine Mitarbeiter hat?
UPDATE:
Wie kann ich die Abfrage ändern, um 0 und keine Ausnahme zu erhalten?
maxShoeSize
?" wenn du es schon ausprobiert hättest.Antworten:
Die Nullstellung
DefaultIfEmpty
ist nicht erforderlich.quelle
Max()
einer leeren Sequenz zu einem Fehler.Ich weiß, dass dies eine alte Frage ist und die akzeptierte Antwort funktioniert, aber diese Frage beantwortete meine Frage, ob eine solche leere Menge zu einer Ausnahme oder einem
default(int)
Ergebnis führen würde.Die akzeptierte Antwort ist jedoch, obwohl sie funktioniert, meiner Meinung nach nicht die ideale Lösung, die hier nicht angegeben wird. Daher gebe ich es in meiner eigenen Antwort zum Nutzen aller, die danach suchen.
Der ursprüngliche Code des OP war:
So würde ich es schreiben, um Ausnahmen zu vermeiden und ein Standardergebnis bereitzustellen:
Dies bewirkt den Rückgabetyp des
Max
Funktion lautetint?
, wodurch dasnull
Ergebnis zugelassen und??
dasnull
Ergebnis durch ersetzt wird0
.BEARBEITEN
Um etwas aus den Kommentaren zu verdeutlichen, unterstützt Entity Framework das
as
Schlüsselwort derzeit nicht. Die Vorgehensweise bei der Arbeit mit EF lautet also wie folgt :Da
[TypeOfWorkers]
dies ein langer Klassenname sein könnte und das Schreiben mühsam ist, habe ich eine Erweiterungsmethode hinzugefügt, um zu helfen.Dies funktioniert nur
int
, aber das gleiche könnte getan werdenlong
,double
oder jeder anderen Werttyp Sie benötigen. Die Verwendung dieser Erweiterungsmethode ist sehr einfach. Sie übergeben einfach Ihre Auswahlfunktion und geben optional einen Wert für null an, der standardmäßig 0 ist. Das oben Gesagte könnte also wie folgt umgeschrieben werden:Hoffentlich hilft das den Leuten noch mehr.
quelle
DefaultIfEmpty
Antwort funktioniert nur dann gut, wennMax
keine Bewertung durchgeführt wird.Select
als Mittelsmann zu arbeiten, wenn ich nur eine Aggregatfunktion wieMax
im Ergebnis verwenden werde. Ich denke auch (ich habe dies noch nicht getestet), dass das generierte SQL eine zusätzliche Unterauswahlabfrage verwenden würde, während meine nur eine leere Menge behandeln würde, indem sie null zurückgibt. Danke für das Upvote und Feedback! ;)ShoeSize
tatsächlich in einer verwandtenUniform
Entität wäre, nicht verwendenWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, sondern nur die gesamte Auswertung in derMax
Funktion behalten :Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Ich bevorzuge es, in meinen Abfragen so wenig Methoden wie möglich zu verwenden, damit EF die größte Freiheit bei der Entscheidung hat, wie Abfragen effizient erstellt werden sollen. ;-)public static TResult MaxOrDefault<TElement, TResult>(this IQueryable<TElement> items, Expression<Func<TElement, TResult>> selector, TResult defaultValue = default) where TResult : struct => items.Select(selector).Max(item => (TResult?)item) ?? defaultValue;
Max () gibt in diesem Fall nichts zurück.
Es wird eine InvalidOperationException ausgelöst, da die Quelle keine Elemente enthält.
quelle
InvalidOperationException
wenn die Objekte in der Liste vom Typ nicht nullbar sindquelle
Wenn dies Linq to SQL ist, verwende ich es nicht gerne
Any()
da es zu mehreren Abfragen an SQL Server führt.Wenn
ShoeSize
es sich nicht um ein nullbares Feld handelt,.Max(..) ?? 0
funktioniert die Verwendung nur des Felds nicht, aber das Folgende funktioniert:Das ausgegebene SQL wird absolut nicht geändert, aber es gibt 0 zurück, wenn die Sequenz leer ist, weil es das ändert
Max()
, um einint?
anstelle von einem zurückzugebenint
.quelle
(vorausgesetzt, das
ShoeSize
ist vom Typint
)Wenn
Workers
es sich um einDbSet
oderObjectSet
aus Entity Framework handelt, würde Ihre anfängliche Abfrage eine auslösenInvalidOperationException
, sich jedoch nicht über eine leere Sequenz beschweren, sondern sich darüber beschweren, dass der materialisierte Wert NULL nicht in eine konvertiert werden kannint
.quelle
Max löst die System.InvalidOperationException aus. "Sequenz enthält keine Elemente."
quelle
Hinweis: Die Abfrage mit ist
DefaultIfEmpty()
möglicherweise erheblich langsamer . In meinem Fall war das eine einfache Abfrage mit.DefaultIfEmpty(DateTime.Now.Date)
.Ich war zu faul, um es zu profilieren, aber offensichtlich hat EF versucht, alle Zeilen abzurufen und dann den
Max()
Wert zu übernehmen.Fazit: Manchmal ist die Handhabung
InvalidOperationException
die bessere Wahl.quelle
Sie können ein ternäres Element verwenden
.Max()
, um das Prädikat zu behandeln und seinen Wert festzulegen.Sie müssten damit umgehen, dass die
Workers
Sammlung null / leer ist, wenn dies möglich ist, dies hängt jedoch von Ihrer Implementierung ab.quelle
Sie können dies versuchen:
quelle
Sie können überprüfen, ob Mitarbeiter vorhanden sind, bevor Sie Max () ausführen.
quelle