LINQ Single vs First

Solution 1:

If you're expecting a Single record, it's always good to be explicit in your code.

I know others have written why you use one or the other, but I thought I'd illustrate why you should NOT use one, when you mean the other.

Note: In my code, I will typically use FirstOrDefault() and SingleOrDefault() but that's a different question.

Take, for example, a table that stores Customers in different languages using a Composite Key ( ID, Lang ):

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();

This code above introduces a possible logic error ( difficult to trace ). It will return more than one record ( assuming you have the customer record in multiple languages ) but it will always return only the first one... which may work sometimes... but not others. It's unpredictable.

Since your intent is to return a Single Customer use Single();

The following would throw an exception ( which is what you want in this case ):

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();

Then, you simply hit yourself on the forehead and say to yourself... OOPS! I forgot the language field! Following is the correct version:

DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();

First() is useful in the following scenario:

DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();

It will return ONE object, and since you're using sorting, it will be the most recent record that is returned.

Using Single() when you feel it should explicitly always return 1 record will help you avoid logic errors.

Solution 2:

Single will throw an exception if it finds more than one record matching the criteria. First will always select the first record from the list. If the query returns just 1 record, you can go with First().

Both will throw an InvalidOperationException exception if the collection is empty. Alternatively you can use SingleOrDefault(). This won't throw an exception if the list is empty