Specific First Record via LinQ

September 9, 2010

I have not written to this blog in a while. But I will try to more often.

I was looking for  a way in Linq to bring certain records in focus by being first in the sort. After Looking around  and see this post. I came up with the following.

public static class linqExtentions
{
  public static IEnumerable SpecificRecordFirst(this IQueryable query, string PropertyToTest,object PropertyValue)
  {
   Type propertyType = query.GetType().GetGenericArguments()[0];
   PropertyInfo property = propertyType.GetProperty(PropertyToTest, BindingFlags.Instance | BindingFlags.Public);
MethodInfo whereMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "Where").ToArray()[0].MakeGenericMethod(propertyType);

ParameterExpression parameter = Expression.Parameter(propertyType,"m");
MemberExpression member = Expression.MakeMemberAccess(parameter,propertyType.GetProperty(PropertyToTest));
BinaryExpression equal = ParameterExpression.Equal
(
member,
(PropertyValue != null) ? Expression.Constant(PropertyValue, PropertyValue.GetType()) : null
);
LambdaExpression lambda = Expression.Lambda(typeof(Func<,>).MakeGenericType(propertyType, typeof(Boolean)), equal, member.Expression as ParameterExpression);
IQueryable query2 = whereMethod.Invoke(null, new Object[] { query, lambda }) as IQueryable;
if (query2.Count() < 1)                 throw new Exception("SpecificRecordFirst- First Record Doesnt Exist");
if (query2.Count() > 1)
throw new Exception("SpecificRecordFirst- First Record is not unique");
yield return query2.First();
BinaryExpression Notequal = ParameterExpression.NotEqual
(
member,
(PropertyValue != null) ? Expression.Constant(PropertyValue, PropertyValue.GetType()) : null
);
LambdaExpression lambda2 = Expression.Lambda(typeof(Func&lt;,&gt;)
.MakeGenericType(propertyType, typeof(Boolean)), Notequal, member.Expression as ParameterExpression);
IQueryable query3 = whereMethod.Invoke(null, new Object[] { query, lambda2 }) as IQueryable;
foreach (var elem in query3)
{
yield return elem;
}
}
}

I wrote this 6 in the morning. I am wondering If this could be done differently.

EDIT

I thought about this a little more . Here

public static IEnumerable SpecificRecordsFirst(this IQueryable query, Expression<Func> expression)
{
   Func func = expression.Compile();
   var firstRecords = query.Where(func.Invoke);
  foreach (var firstRecord in firstRecords)
  {
     yield return firstRecord;
  }
  var secondRecords = query.Except(firstRecords.AsEnumerable());
  foreach (var secondRecord in secondRecords)
  {
     yield return secondRecord;
  }
}

Much better IMHO