LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria
Consider the IEnumerable extension methods
Returns the only element of a sequence, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.
FirstOrDefault from MSDN (presumably when using an
OrderByDescending() or none at all),
Returns the first element of a sequence
Consider a handful of example queries, it's not always clear when to use these two methods:
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?
What conventions do you follow or suggest when deciding to use
FirstOrDefault() in your LINQ queries?
Whenever you use
SingleOrDefault, you clearly state that the query should result in at most a single result. On the other hand, when
FirstOrDefault is used, the query can return any amount of results but you state that you only want the first one.
I personally find the semantics very different and using the appropriate one, depending on the expected results, improves readability.
If your result set returns 0 records:
SingleOrDefaultreturns the default value for the type (e.g. default for int is 0)
FirstOrDefaultreturns the default value for the type
If you result set returns 1 record:
SingleOrDefaultreturns that record
FirstOrDefaultreturns that record
If your result set returns many records:
SingleOrDefaultthrows an exception
FirstOrDefaultreturns the first record
If you want an exception to be thrown if the result set contains many records, use
If you always want 1 record no matter what the result set contains, use
Read more... Read less...
- a semantical difference
- a performance difference
between the two.
FirstOrDefaultreturns a first item of potentially multiple (or default if none exists).
SingleOrDefaultassumes that there is a single item and returns it (or default if none exists). Multiple items are a violation of contract, an exception is thrown.
FirstOrDefaultis usually faster, it iterates until it finds the element and only has to iterate the whole enumerable when it doesn't find it. In many cases, there is a high probability to find an item.
SingleOrDefaultneeds to check if there is only one element and therefore always iterates the whole enumerable. To be precise, it iterates until it finds a second element and throws an exception. But in most cases, there is no second element.
FirstOrDefaultif you don't care how many items there are or when you can't afford checking uniqueness (e.g. in a very large collection). When you check uniqueness on adding the items to the collection, it might be too expensive to check it again when searching for those items.
SingleOrDefaultif you don't have to care about performance too much and want to make sure that the assumption of a single item is clear to the reader and checked at runtime.
In practice, you use
FirstOrDefault often even in cases when you assume a single item, to improve performance. You should still remember that
SingleOrDefault can improve readability (because it states the assumption of a single item) and stability (because it checks it) and use it appropriately.
Nobody has mentioned that FirstOrDefault translated in SQL does TOP 1 record, and SingleOrDefault does TOP 2, because it needs to know is there more than 1 record.
For LINQ -> SQL:
- will generate query like "select * from users where userid = 1"
- Select matching record, Throws exception if more than one records found
- Use if you are fetching data based on primary/unique key column
- will generate query like "select top 1 * from users where userid = 1"
- Select first matching rows
- Use if you are fetching data based on non primary/unique key column
SingleOrDefault in situations where my logic dictates that the will be either zero or one results. If there are more, it's an error situation, which is helpful.
SingleOrDefault: You're saying that "At most" there is one item matching the query or default FirstOrDefault: You're saying that there is "At least" one item matching the query or default
Say that out loud next time you need to choose and you shall likely choose wisely. :)