Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sequence contains more than one element - SingleOrDefault not helping

I have the line below but still get an exception "Sequence contains more than one element"

Details rd = this.db.Details.SingleOrDefault(x => x.TId == Id && x.TypeId == TypeId); 

I was hoping that SingleOrDefault would avoid the exception.

like image 657
StackTrace Avatar asked Mar 27 '14 15:03

StackTrace


People also ask

What exception does SingleOrDefault throw?

SingleOrDefault<TSource>(IEnumerable<TSource>) 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.

What is the difference between FirstOrDefault and SingleOrDefault?

SingleOrDefault() – Same as Single(), but it can handle the null value. First() - There is at least one result, an exception is thrown if no result is returned. FirstOrDefault() - Same as First(), but not thrown any exception or return null when there is no result.


1 Answers

SingleOrDefault returns a SINGLE element or null if no element is found. If 2 elements are found in your Enumerable then it throws the exception you are seeing. Just like Highlander... with Single - there can be only one.

FirstOrDefault returns the FIRST element it finds or null if no element is found. so if there are 2 elements that match your predicate the second one is ignored.

Assuming you don't care if there are multiple matches and you only want the first one or null if no match is found... then you probably want the following...

Details rd = this.db.Details     .FirstOrDefault(x => x.TId == Id && x.TypeId == TypeId); 

Note that both of these methods only return one element they only differ in what they do after they find a match. First stops looking at that point and returns what it found, Single keeps checking the rest of the list to make sure there are no more matches. The OrDefault part determines what it returns if no match is found. SingleOrDefault or FirstOrDefault returns null if no value is found but if you just use Single or First then it MUST find one match or it will throw an exception.

EDIT: Good point Steve Since First returns the first element you may need to use an OrderBy in order to make sure the element you want is indeed first. For instance... suppose your object had an UpdateDate property and you wanted the object with the most recent UpdateDate...

Details rd = this.db.Details     .OrderByDescending(x => x.UpdateDate)     .FirstOrDefault(x => x.TId == Id && x.TypeId == TypeId); 
like image 61
Kevin Avatar answered Oct 05 '22 17:10

Kevin