Mike Taulty's Blog
Bits and Bytes from Microsoft UK
More Dynamic Queries

Blogs

Mike Taulty's Blog

Elsewhere

Archives

Took this slightly further (which you could definitely describe as making it worse :-)) by adding a limited form of an OrElse;

namespace MyExtensions
{
  public enum Operand
  {
    Equal,
    NotEqual,
    LessThan,
    LessThanEqual,
    GreaterThan,
    GreaterThanEqual
  }
  public static class Extensions
  {
    public static IQueryable<T> AddOrElse<T, V, U>(this IQueryable<T> queryable,
      string lhsName, Operand lhsOperand, V lhsValue,
      string rhsName, Operand rhsOperand, U rhsValue)
    {
      ParameterExpression pe = Expression.Parameter(typeof(T), "p");

      IQueryable<T> query = queryable.Where<T>(
        Expression.Lambda<Func<T, bool>>(Expression.OrElse(
          MakeBinaryExpression<T, V>(pe, lhsName, lhsOperand, lhsValue),
          MakeBinaryExpression<T, U>(pe, rhsName, rhsOperand, rhsValue)),
          new ParameterExpression[] { pe }));

      return (query);
    }
    public static IQueryable<T> AddClause<T, V>(this IQueryable<T> queryable,
      string propertyName, Operand operand, V propertyValue)
    {
      ParameterExpression pe = Expression.Parameter(typeof(T), "p");

      IQueryable<T> query = queryable.Where<T>(
        Expression.Lambda<Func<T, bool>>(
          MakeBinaryExpression<T, V>(pe, propertyName, operand, propertyValue),
          new ParameterExpression[] { pe }));

      return (query);
    }
    private static BinaryExpression MakeBinaryExpression<T, V>(
      ParameterExpression parameter, string propertyName, Operand operand, V propertyValue)
    {
      Func<Expression, Expression, bool, MethodInfo, BinaryExpression>
        fn = GetFuncForOperand(operand);

      BinaryExpression expression =
          fn(Expression.Property(
            parameter,
            typeof(T).GetProperty(propertyName)),
            Expression.Constant(propertyValue, typeof(V)),
            false,
            null);

      return (expression);
    }
    private static Func<Expression, Expression, bool, MethodInfo, BinaryExpression> GetFuncForOperand(Operand operand)
    {
      Func<Expression, Expression, bool, MethodInfo, BinaryExpression> func = null;

      switch (operand)
      {
        case Operand.Equal:
          func = Expression.Equal;
          break;
        case Operand.NotEqual:
          func = Expression.NotEqual;
          break;
        case Operand.LessThan:
          func = Expression.LessThan;
          break;
        case Operand.LessThanEqual:
          func = Expression.LessThanOrEqual;
          break;
        case Operand.GreaterThan:
          func = Expression.GreaterThan;
          break;
        case Operand.GreaterThanEqual:
          func = Expression.GreaterThanOrEqual;
          break;
        default:
          break;
      }
      return (func);
    }
  }
}

 

and then that can be used as in;

 static void Main(string[] args)
    {
      NorthwindDataContext ctx = new NorthwindDataContext("server=.;database=northwind");

      var query = from p in ctx.Products
                  select p;

      int prod = 22;
      short? units = 120;

      query = query.AddOrElse(
        "ProductID", Operand.Equal, prod,
        "UnitsInStock", Operand.GreaterThan, units);

      foreach (Product v in query)
      {
        Console.WriteLine(v.ProductID);
      }
    }

 

I'm going to stop doing this now - it's making my head hurt :-)


Posted Mon, Jun 18 2007 5:08 AM by mtaulty

Comments

Mike Taulty's Blog wrote Messing with Dynamic LINQ Queries
on Thu, Sep 11 2008 9:08 AM
Mike was chatting to me about how you'd take something like this ( against LINQ to SQL and the Northwind...