IQueryable extension methods SingleOrNull FirstOrNull OrderBy

In my dev work I constantly discover that readability of code – clarity of what is going on – is very important in writing quality manageable code.

Even simple extension methods that help code to be more readable on the first sight are useful to me.

It this post I’ll share with you two (three) simple ‘replacements’ / enhancements :

  • SingleOrNull / FirstOrNull replacement for SingleOrDefault / FirstOrDefault
  • OrderBy extension with Descending/Ascending direction as method argument

Why not just SingleOrDefault(..) / FirstOrDefault(..) ?

Because I’m often unsure what will be the ‘default’ value, null or some ‘default’.
I want to be absolutely sure it’s null (for reference types).
I want it to be stated explicit in code.

// this is much more readable: 
var result = queryObject.SingleOrNull();
// than this: 
var result = queryObject.SingleOrDefault();

One can say that’s tiny difference. But such tiny differences in large number makes The Difference & code more readable.
In addition when Single is violated (multiple elements), I throw specific ‘typed’ exception MultipleOnSingleEx instead of InvalidOperationException for easier error handling & logging.

// ### SingleOrNull
public static T SingleOrNull(this IQueryable iQ, System.Linq.Expressions.Expression> predicate) where T : class
{
   try
   {
      var res = iQ.SingleOrDefault(predicate);
      return res == default(T) ? null : res;
   }
   catch (InvalidOperationException invOpEx)
   {
      if (invOpEx.Message == "Sequence contains more than one element")
         throw new MultipleOnSingleEx(invOpEx.Message, invOpEx);
      throw;
   }
}
public static T SingleOrNull(this IQueryable iQ) where T : class
{
   try
   {
      var res = iQ.SingleOrDefault();
      return res == default(T) ? null : res;	
   }
   catch (InvalidOperationException invOpEx)
   {
      if (invOpEx.Message == "Sequence contains more than one element")
         throw new MultipleOnSingleEx(invOpEx.Message, invOpEx);
      throw;
   }
}

// ### FirstOrNull
public static T FirstOrNull(this IQueryable iQ, System.Linq.Expressions.Expression> predicate) where T : class
{
   var res = iQ.FirstOrDefault(predicate);
   return res == default(T) ? null : res;
}
public static T FirstOrNull(this IQueryable iQ) where T : class
{
   var res = iQ.FirstOrDefault();
   return res == default(T) ? null : res;
}

/// <summary>
/// Multiple elements encountered on IQueryable.Single ... ()
/// This exception encapsulates System.InvalidOperationException: Sequence contains more than one element
/// </summary>
public class MultipleOnSingleEx : Exception
{
   public MultipleOnSingleEx(SerializationInfo info, StreamingContext context) : base(info, context) { }
   public MultipleOnSingleEx(string message, Exception innerException) : base(message, innerException) { }
   public MultipleOnSingleEx(string message) : base(message) { }
   public MultipleOnSingleEx() { }
}

IQueryable .OrderBy( predicate , bool isDescending)

Why such a feature is usefull ?
Because you don’t need two if(..) .. else … branches based on ascending / descending parameter if it’s runtime dynamic (ex.: based on user action).
It’s ever more important when dynamically constructing large queries.

public static IOrderedQueryable OrderBy(this IQueryable iQ, System.Linq.Expressions.Expression> predicate, bool isDescending)
   where T : class
{
   return isDescending ? iQ.OrderByDescending(predicate) : iQ.OrderBy(predicate);
}

Hope it helps a bit in your work.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s