I'm getting an exception whenever I fetch like this
Feature f = o.Features.SingleOrDefault(e => e.LinkName == PageLink);
because this can return one or more than one element. What is the alternative approach that I can use to solve this issue?
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.
SingleOrDefault() will return default value of a data type of generic collection if there is no elements in a colection or for the specified condition. SingleOrDefault() will throw an exception if there is more than one elements in a colection or for the specified condition.
When you want a default value is returned if the result set contains no record, use SingleOrDefault. When you always want one record no matter what the result set contains, use First or FirstOrDefault. When you want a default value if the result set contains no record, use FirstOrDefault.
The major difference between First() and FirstOrDefault() is First will throw an exception when there are no results and FirstOrDefault won't. In fact, FirstOrDefault will simply return the null value (reference types) or the default value of the value type.
Single
and SingleOrDefault
are designed to throw if more that one match exists in the sequence. A consequence of this is that the entire sequence must be iterated prior to completion. It does not sound like this is what you want. Try FirstOrDefault
instead:
Feature f = o.Features
.FirstOrDefault(e => e.vcr_LinkName == PageLink && e.bit_Activate == true);
This will (generally) perform better because it completes as soon as a match is found.
Of course, if you actually want to retain more than one element, a Where
clause would be more appropriate:
IEnumerable<Feature> fs = o.Features
.Where(e => e.vcr_LinkName == PageLink && e.bit_Activate == true);
Alternatively, if you only want the item when there is exactly one match and do not want to throw when there are more than one, this can be easily accomplished. I've created an extension method for this in my project:
public static class QueryableExtensions
{
public static TSource SingleWhenOnly<TSource>(this IQueryable<TSource> source)
{
if (source == null)
throw new ArgumentNullException("source");
var results = source.Take(2).ToArray();
return results.Length == 1 ? results[0] : default(TSource);
}
public static TSource SingleWhenOnly<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
if (source == null)
throw new ArgumentNullException("source");
if (predicate == null)
throw new ArgumentNullException("predicate");
var results = source.Where(predicate).Take(2).ToArray();
return results.Length == 1 ? results[0] : default(TSource);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With