Replace Operator in Where Lambda Section with Parameter

I want to replace operator (==,> =,> ...) in the where clause of linq lambda with a parameter passed in the method

method:

public IEnumerable<Localisation> GetByFiltre(string filter, string valeurDate1)

/*
filter has the value of an operator:
>
==
!=
>=
<=
*/

    DateTime dt = Convert.ToDateTime(valeurDate1);

    var mod = from o in new GpsContext().Locals.Where(loc => loc.Date == dt)

      

I want to replace == in a sentence where with a parameter filter get something like this

     var mod = from o in new GpsContext().Locals.Where(loc => loc.Date filter dt)

      

does any body know how to make it work?

+1


source to share


5 answers


I think it is better to make a dictionary of string filters and corresponding delegates.



class YourClass
{
     static readonly Dictionary<string, Func<DateTime, DateTime, bool>> s_filters = new Dictionary<string, Func<DateTime, DateTime, bool>>
     {
       {  ">", new Func<DateTime, DateTime, bool>((d1, d2) => d1  > d2) }
       { "==", new Func<DateTime, DateTime, bool>((d1, d2) => d1 == d2) }
       { "!=", new Func<DateTime, DateTime, bool>((d1, d2) => d1 != d2) }
       { ">=", new Func<DateTime, DateTime, bool>((d1, d2) => d1 >= d2) }
       { "<=", new Func<DateTime, DateTime, bool>((d1, d2) => d1 <= d2) }
     };

     public IEnumerable<Localisation> GetByFiltre(string filter, string valeurDate1)
     {
        ...

        DateTime dt = Convert.ToDateTime(valeurDate1);
        var filterDelegate = s_filters[filter];

        var mod = from o in new GpsContext().Locals.Where(loc => filterDelegate(loc.Date,dt));

        ...
     }
}

      

+3


source


There is a good library for parsing strings in Lamdba expressions described here.

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

and downloadable here

http://msdn2.microsoft.com/en-us/vcsharp/bb894665.aspx



It has pretty good expression syntax that allows you to express quite a few different queries and operations.

Remember, depending on the request, you may lose some security. In cases where the operations are ok, but any projector where the lambda selection is parsed from a string cannot be output by the compiler. This means that you end up with not generic IQueryables and not typically typed ones. Sometimes this is fine, but it prevents you from using generic extension methods later in the request.

Edit to clarify things with non-generic queries. ... The library contains a set of non-generic versions of query extension methods that accept string representations of expressions and operate on an unequal IQueryable. If you look at the code, it's pretty easy to see how to write them if the one you want doesn't exist. For example, I needed to make a non-general video, and it only took a couple of hours.

+1


source


I found a solution to your problem that works like this:

var test = dataContext.Interactions.DynamicWhere<Interaction,DateTime>("Created_Month", ExpressionType.LessThan, DateTime.Now);

      

You can use any ExpressionType

- equals, less, more, etc., and it will translate to T-SQL if possible (so the filtering will be done on the server). It will also work in memory on IEnumerables

.

Here's the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace WindowsFormsApplication1
{
    public static class GenericFilterExtension
    {
        public static IQueryable<TRow> DynamicWhere<TRow,TColumn>(this IQueryable<TRow> input, string field, ExpressionType binaryOperator, TColumn value)
        {
            var exp = MakeWhereLambda<TRow, TColumn>(field, binaryOperator, value) as Expression<Func<TRow, bool>>;    
            return input.Where(exp);
        }

        public static IEnumerable<TRow> DynamicWhere<TRow, TColumn>(this IEnumerable<TRow> input, string field, ExpressionType binaryOperator, TColumn value)
        {
            var exp = MakeWhereLambda<TRow, TColumn>(field, binaryOperator, value).Compile() as Func<TRow, bool>;    
            return input.Where(exp);
        }

        private static LambdaExpression MakeWhereLambda<TRow, TColumn>(string field, ExpressionType binaryOperator, TColumn value)
        {
            var param = Expression.Parameter(typeof(TRow), "n");
            var op = Expression.MakeBinary(binaryOperator, Expression.Property(param, field), Expression.Constant(value));    
            return Expression.Lambda(op, new ParameterExpression[] { param });
        }
    }
}

      

+1


source


You can pass a function that is a where clause, for example.

public IEnumerable<Localisation> GetByFiltre(Func<IEnumerable<localisation>, IEnumerable<localisation>> whereClause)
{
    /*
    filter has the value of an operator:
    >
    ==
    !=
    >=
    <=
    */

    DateTime dt = Convert.ToDateTime(valeurDate1);

    var mod = whereClause(new GpsContext().Locals);
}

      

And call it with:

GetByFiltre(f => f.Where(d => d.Date > SomeDate));

      

0


source


And the filter must contain "==", "> =", etc.? You can parse a filter string in the traditional way:

var mod = from o in new GpsContext().Locals.Where(loc => 
{
    switch(filter)
    {
        case "==":
            return loc.Date == dt;
        case ">=":
            return loc.Date >= dt;
        // ...
    }
})

      

-1


source







All Articles