I'm having a devil of a time finding a comparison of the different ways to query for a single item, and when to use each.
Does anyone have a link that compares all these, or a quick explanation as to why you would use one over the other? Are there still more operators that I am unaware of?
Thank you.
Here is an overview of the different methods:
Find() - when you want to get an item by primary key. This will return null if it can't find an item. It will look in the context before going to the database (as pointed out by Yaron in the comments) which can be an important efficiency factor if you need to get the same entity multiple times while the same context is alive.
Single() - when you expect exactly one item to be returned by a query. This will throw an exception if the query does not return exactly one item.
SingleOrDefault() - when you expect zero or one items to be returned by a query (i.e. you are not sure if an item with a given key exists). This will throw an exception if the query does not return zero or one items.
First() - when you expect one or more items to be returned by a query but you only want to access the first item in your code (ordering could be important in the query here). This will throw an exception if the query does not return at least one item.
FirstOrDefault() - when you expect zero or more items to be returned by a query but you only want to access the first item in your code (i.e. you are not sure if an item with a given key exists)
Single() and SingleOrDefault() is usually used on unique identifiers such as IDs, while First() or FirstOrDefault() is usually used for a query that could have multiple result but you want only the "Top 1".
Single() or First() would throw an exception if no result is returned, SingleOrDefault() and FirstOrDefault() catches the exception and returns null or default(ResultDataType).
It's really very simple:
Single
returns a single item and throw an exception if there is either none or more than one item.First
will return the first item or throw when there is no item.FirstOrDefault
will return the first item or return the default value (which isnull
in case the given type is a reference type) when there is no item.This is the behavior the API is supposed to have. Note however that the underlying implementation could have a different behavior. While Entity Framework obeys this, a O/RM like LLBLGen can also return
null
when callingFirst
which is a very strange thing. This was a very strange (and stubborn) decision by the designer IMO.On the other side, you can divide these methods by the core logic, like this:
For some performance details, especially in the second case you can look here: https://msdn.microsoft.com/en-us/data/hh949853.aspx?f=255&MSPPError=-2147217396#3
In addition, in the first group you can define complex queries, but with Find() method you can provide only entity key for search.
I always tend to use FirstOrDefault. If you really want to be picky with performance then you should use FirstOrDefault in EF. Under the covers SingleOrDefault uses top (2) in the query because, it needs to check if there is a second row that matches the criteria and if it does, it throws an exception. Basically in SingleOrDefault you are saying that u care to throw an exception if your query returns more then 1 record.
The four methods each have their place; Though you really only have two different operations.
The xxxxOrDefault() version just adds on "I don't want to consider an empty result set to be an exceptional circumstance."