J'ai cette question:
int maxShoeSize = Workers
.Where(x => x.CompanyId == 8)
.Max(x => x.ShoeSize);
Que se passera-t-il maxShoeSize
si l'entreprise 8 n'a pas du tout de travailleurs?
MISE À JOUR:
Comment puis-je changer la requête pour obtenir 0 et pas une exception?
maxShoeSize
?" si vous l'aviez déjà essayé.Réponses:
Le zéro
DefaultIfEmpty
n'est pas nécessaire.la source
Max()
à une séquence vide entraîne une erreur.Je sais que c'est une vieille question et que la réponse acceptée fonctionne, mais cette question a répondu à ma question de savoir si un tel ensemble vide entraînerait une exception ou un
default(int)
résultat.La réponse acceptée cependant, bien que cela fonctionne, n'est pas la solution idéale à mon humble avis, qui n'est pas donnée ici. Ainsi je le fournis dans ma propre réponse pour le bénéfice de tous ceux qui le recherchent.
Le code original de l'OP était:
Voici comment je l'écrirais pour éviter les exceptions et fournir un résultat par défaut:
Cela provoque le type de retour de la
Max
fonctionint?
, ce qui autorise lenull
résultat, puis??
remplace lenull
résultat par0
.EDIT
Juste pour clarifier quelque chose à partir des commentaires, Entity Framework ne prend actuellement pas en charge le
as
mot - clé, donc la façon de l'écrire lorsque vous travaillez avec EF serait:Comme le
[TypeOfWorkers]
peut être un nom de classe long et qu'il est fastidieux à écrire, j'ai ajouté une méthode d'extension pour vous aider.Cela ne les poignées
int
, mais la même chose pourrait être fait pourlong
,double
ou tout autre type de valeur que vous avez besoin. L'utilisation de cette méthode d'extension est très simple, il vous suffit de passer votre fonction de sélection et d'inclure éventuellement une valeur à utiliser pour null, qui vaut par défaut 0. Donc, ce qui précède pourrait être réécrit comme suit:Espérons que cela aide encore plus les gens.
la source
DefaultIfEmpty
réponse la plus populaire ne fonctionne bien que lorsque vousMax
ne faites pas d'évaluation.Select
comme intermédiaire quand je vais juste utiliser une fonction d'agrégation commeMax
sur le résultat. Je pense également (je ne l'ai pas encore testé) que le SQL généré utiliserait une requête de sous-sélection supplémentaire en faisant cela, tandis que le mien traiterait simplement un ensemble vide en retournant null. Merci pour le vote positif et les commentaires! ;)ShoeSize
était en fait dans une liéeUniform
entité, je ne voudrais pas utiliserWorkers.Where(x => x.CompanyId == 8).Select(x => x.Uniform).Max(x => x.ShoeSize)
, au lieu que je voudrais juste garder toute l'évaluation dans laMax
fonction:Workers.Where(x => x.CompanyId == 8).Max(x => x.Uniform.ShoeSize)
. Je préfère utiliser le moins de méthodes possible dans mes requêtes pour permettre à EF d'avoir la plus grande liberté pour décider comment construire efficacement des requêtes. ;-)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 () ne retournera rien dans ce cas.
Cela lèvera InvalidOperationException car la source ne contient aucun élément.
la source
InvalidOperationException
si les objets de la liste sont de type non nullablela source
S'il s'agit de Linq to SQL, je n'aime pas l'utiliser
Any()
car cela entraîne plusieurs requêtes sur le serveur SQL.Si ce
ShoeSize
n'est pas un champ Nullable, utiliser uniquement le.Max(..) ?? 0
ne fonctionnera pas, mais ce qui suit:Cela ne change absolument pas le SQL émis, mais il renvoie 0 si la séquence est vide car il change le
Max()
pour retourner unint?
au lieu d'unint
.la source
(en supposant que
ShoeSize
c'est de typeint
)Si
Workers
est unDbSet
ouObjectSet
depuis Entity Framework, votre requête initiale lèverait unInvalidOperationException
, mais ne se plaignant pas d'une séquence vide, mais se plaignant que la valeur matérialisée NULL ne peut pas être convertie en unint
.la source
Max lancera System.InvalidOperationException "La séquence ne contient aucun élément"
la source
NB: la requête avec
DefaultIfEmpty()
peut être significativement plus lente . Dans mon cas, c'était une simple requête avec.DefaultIfEmpty(DateTime.Now.Date)
.J'étais trop paresseux pour le profiler, mais évidemment EF a essayé d'obtenir toutes les lignes, puis de prendre la
Max()
valeur.Conclusion: la manipulation
InvalidOperationException
peut parfois être le meilleur choix.la source
Vous pouvez utiliser un ternaire à l'intérieur
.Max()
pour gérer le prédicat et définir sa valeur;Vous devrez gérer la
Workers
collection comme étant nulle / vide si c'est une possibilité, mais cela dépendra de votre implémentation.la source
Vous pouvez essayer ceci:
la source
Vous pouvez vérifier s'il y a des ouvriers avant de faire Max ().
la source