Considérez les méthodes d'extension IEnumerable SingleOrDefault()
etFirstOrDefault()
Documents MSDN quiSingleOrDefault
:
Renvoie le seul élément d'une séquence ou une valeur par défaut si la séquence est vide; cette méthode lève une exception s'il y a plus d'un élément dans la séquence.
tandis que FirstOrDefault
de MSDN (probablement lors de l' utilisation d' un OrderBy()
ou OrderByDescending()
ou pas du tout),
Renvoie le premier élément d'une séquence
Considérez quelques exemples de requêtes, il n'est pas toujours clair quand utiliser ces deux méthodes:
var someCust = db.Customers
.SingleOrDefault(c=>c.ID == 5); //unlikely(?) to be more than one, but technically COULD BE
var bobbyCust = db.Customers
.FirstOrDefault(c=>c.FirstName == "Bobby"); //clearly could be one or many, so use First?
var latestCust = db.Customers
.OrderByDescending(x=> x.CreatedOn)
.FirstOrDefault();//Single or First, or does it matter?
Question
Quelles conventions suivez-vous ou suggérez-vous lorsque vous décidez d'utiliser SingleOrDefault()
et FirstOrDefault()
dans vos requêtes LINQ?
la source
Si votre jeu de résultats renvoie 0 enregistrements:
SingleOrDefault
renvoie la valeur par défaut du type (par exemple, la valeur par défaut pour int est 0)FirstOrDefault
renvoie la valeur par défaut du typeSi votre jeu de résultats renvoie 1 enregistrement:
SingleOrDefault
renvoie cet enregistrementFirstOrDefault
renvoie cet enregistrementSi votre jeu de résultats renvoie de nombreux enregistrements:
SingleOrDefault
lève une exceptionFirstOrDefault
renvoie le premier enregistrementConclusion:
Si vous souhaitez qu'une exception soit levée si le jeu de résultats contient de nombreux enregistrements, utilisez
SingleOrDefault
.Si vous voulez toujours 1 enregistrement, quel que soit le jeu de résultats, utilisez
FirstOrDefault
la source
FirstOrDefault
est retourné premier enregistrement signifie nouvel enregistrement (dernier) / ancien enregistrement (premier)? pouvez-vous me préciser?Il y a
entre les deux.
Différence sémantique:
FirstOrDefault
renvoie un premier élément potentiellement multiple (ou par défaut s'il n'en existe aucun).SingleOrDefault
suppose qu'il existe un seul élément et le renvoie (ou par défaut s'il n'en existe aucun). Plusieurs articles constituent une violation du contrat, une exception est levée.Différence de performance
FirstOrDefault
est généralement plus rapide, il itère jusqu'à ce qu'il trouve l'élément et n'a à répéter l'ensemble de l'énumérable que lorsqu'il ne le trouve pas. Dans de nombreux cas, il y a une forte probabilité de trouver un article.SingleOrDefault
doit vérifier s'il n'y a qu'un seul élément et itère donc toujours l'ensemble de l'énumérable. Pour être précis, il itère jusqu'à ce qu'il trouve un deuxième élément et lève une exception. Mais dans la plupart des cas, il n'y a pas de second élément.Conclusion
À utiliser
FirstOrDefault
si vous ne vous souciez pas du nombre d'articles ou si vous ne pouvez pas vous permettre de vérifier l'unicité (par exemple dans une très grande collection). Lorsque vous vérifiez l'unicité de l'ajout des éléments à la collection, il peut être trop coûteux de le vérifier à nouveau lors de la recherche de ces éléments.À utiliser
SingleOrDefault
si vous n'avez pas trop à vous soucier des performances et que vous voulez vous assurer que l'hypothèse d'un seul élément est claire pour le lecteur et vérifiée lors de l'exécution.En pratique, vous utilisez
First
/FirstOrDefault
souvent même dans les cas où vous supposez un seul élément, pour améliorer les performances. Vous devez toujours vous rappeler queSingle
/SingleOrDefault
peut améliorer la lisibilité (car il énonce l'hypothèse d'un seul élément) et la stabilité (car il le vérifie) et l'utiliser de manière appropriée.la source
SingleOrDefault
itérer sur un grand nombre d'objets lors de l'utilisation de Linq to Objects, mais n'a pasSingleOrDefault
à répéter au plus 2 éléments si Linq parle à une base de données par exemple? Je me demande juste ..Enumerable
.Personne n'a mentionné que FirstOrDefault traduit en SQL fait TOP 1 enregistrement, et SingleOrDefault fait TOP 2, car il a besoin de savoir qu'il y a plus d'un enregistrement.
la source
FirstOrDefault()
ajouteLIMIT 0,1
tout enSingleOrDefault()
n'ajoute rien.Pour LINQ -> SQL:
SingleOrDefault
FirstOrDefault
la source
J'utilise
SingleOrDefault
dans des situations où ma logique dicte que le résultat sera soit zéro soit un résultat. S'il y en a plus, c'est une situation d'erreur, ce qui est utile.la source
SingleOrDefault: vous dites que "au plus" il y a un élément correspondant à la requête ou par défaut FirstOrDefault: vous dites qu'il y a "au moins" un élément correspondant à la requête ou par défaut
Dites-le à voix haute la prochaine fois que vous devez choisir et vous choisirez probablement judicieusement. :)
la source
FirstOrDefault. More correctly:
FirstOrDefault` = N'importe quel nombre de résultats, mais je ne me soucie que du premier, il peut également n'y avoir aucun résultat.SingleOrDefault
= Il y a 1 ou 0 résultats, s'il y en a plus, cela signifie qu'il y a une erreur quelque part.First
= Il y a au moins un résultat, et je le veux.Single
= Il y a exactement 1 résultat, ni plus, ni moins, et je veux celui-là.Dans vos cas, j'utiliserais ce qui suit:
sélectionnez par ID == 5: c'est OK d'utiliser SingleOrDefault ici, car vous vous attendez à une [ou aucune] entité, si vous avez plus d'une entité avec ID 5, il y a quelque chose de mal et certainement une exception digne.
lors de la recherche de personnes dont le prénom est égal à "Bobby", il peut y en avoir plusieurs (très probablement, je pense), vous ne devez donc ni utiliser Single ni First, sélectionnez simplement avec l'opération Where (si "Bobby" renvoie trop entités, l'utilisateur doit affiner sa recherche ou choisir l'un des résultats renvoyés)
l'ordre par date de création doit également être effectué avec une opération Where (il est peu probable qu'il n'y ait qu'une seule entité, le tri ne serait pas très utile;) cela implique cependant que vous voulez que TOUTES les entités soient triées - si vous n'en voulez qu'une, utilisez FirstOrDefault, Single lancerait à chaque fois si vous aviez plus d'une entité.
la source
Les deux sont les opérateurs d'élément et ils sont utilisés pour sélectionner un seul élément dans une séquence. Mais il y a une différence mineure entre eux. L'opérateur SingleOrDefault () lèverait une exception si plusieurs éléments sont satisfaits, la condition où FirstOrDefault () ne lèvera aucune exception pour la même chose. Voici l'exemple.
la source
Dans votre dernier exemple:
Oui. Si vous essayez d'utiliser
SingleOrDefault()
et que la requête aboutit à plus d'un enregistrement, vous obtiendrez une exception. Le seul moment où vous pouvez utiliser en toute sécuritéSingleOrDefault()
est lorsque vous n'attendez qu'un seul et un seul résultat ...la source
Donc, si je comprends bien maintenant,
SingleOrDefault
sera bien si vous recherchez des données qui sont garanties d'être uniques, c'est-à-dire appliquées par des contraintes de base de données comme la clé primaire.Ou existe-t-il un meilleur moyen d'interroger la clé primaire?
En supposant que ma TableAcc a
et je veux demander un
AccountNumber 987654
, j'utilisela source
À mon avis,
FirstOrDefault
est beaucoup surutilisé. Dans la majorité des cas, lorsque vous filtrez des données, vous vous attendez à récupérer une collection d'éléments correspondant à la condition logique ou un seul élément unique par son identifiant unique - tel qu'un utilisateur, un livre, une publication, etc. pourquoi nous pouvons même aller jusqu'à dire queFirstOrDefault()
c'est une odeur de code non pas parce qu'il y a quelque chose qui ne va pas mais parce qu'il est utilisé trop souvent. Ce billet de blog explore le sujet en détail. La plupart du temps, l'OMISingleOrDefault()
est une bien meilleure alternative, alors faites attention à cette erreur et assurez-vous d'utiliser la méthode la plus appropriée qui représente clairement votre contrat et vos attentes.la source
Une chose qui manque dans les réponses ...
S'il y a plusieurs résultats, FirstOrDefault sans commande par peut ramener des résultats différents en fonction de la stratégie d'indexation utilisée par le serveur.
Personnellement, je ne supporte pas de voir FirstOrDefault dans le code car pour moi, cela dit que le développeur ne se souciait pas des résultats. Avec une commande par, elle peut être utile comme moyen de faire respecter le plus récent / le plus tôt. J'ai dû corriger de nombreux problèmes causés par des développeurs imprudents utilisant FirstOrDefault.
la source
J'ai interrogé Google pour l'utilisation des différentes méthodes sur GitHub. Pour ce faire, exécutez une requête de recherche Google pour chaque méthode et limitez la requête au domaine github.com et à l'extension de fichier .cs en utilisant la requête "site: fichier github.com: cs ..."
Il semble que les méthodes First * soient plus couramment utilisées que les méthodes Single *.
la source
Je ne comprends pas pourquoi vous utilisez
FirstOrDefault(x=> x.ID == key)
alors que cela pourrait récupérer des résultats beaucoup plus rapidement si vous utilisezFind(key)
. Si vous interrogez avec la clé primaire de la table, la règle générale est de toujours utiliserFind(key)
.FirstOrDefault
devrait être utilisé pour des trucs de prédicat comme(x=> x.Username == username)
etc.cela ne méritait pas un downvote car le titre de la question n'était pas spécifique à linq sur DB ou Linq à List / IEnumerable etc.
la source
Find()
?