Dynamic LINQ - Is There A .NET 4 Version?
Asked Answered
F

4

31

I'm looking to use LINQ for some searching routines and wanted to have some dynamic where clauses. So, for example, if a user wants to search by city or search by state, I would have a dynamic LINQ Where<> call instead of creating two strongly typed LINQ expressions and then using the appropriate one based on how the user wants to search.

So I would like to do this:

String criteria="p.City='Pittsburgh'";  //or "p.State='PA'"
personData.Where(criteria)

instead of

personData.Where(p => p.City=="Pittsburgh");

or

personData.Where(p => p.State=="PA");

I came across a blog post by Scott Guthrie talking about Dynamic LINQ in the Visual Studio 2008 samples. This seems to do what I want, but my questions are:

  1. Is this sample library supported by Microsoft?
  2. Scott Guthrie's article is in regards to VS2008 (.NET 3.5). Is there a better option for .NET 4? Maybe something that was released with .NET 4 that accomplishes the same thing (or something very close)?

Thanks in advance!

Fash answered 2/3, 2011 at 3:43 Comment(7)
I can see immediate flaw. You don't get compile time checking of your LINQ comparers. If you can't see why this would be useful, have a look at your criteria string...Sorely
Why would you want this? It seems to be trying to be clever, for the sake of being clever.Gibberish
@Sergio: This is helpful for things like jqGrid where search terms are returned as strings to your controllers. Its nice to have a framework handle it rather than have a bunch of boilerplate code.Botvinnik
@David Hoerster: I remember having some trouble with this library. I found it better to develop the expressions I needed. This article demonstrates custom expressions (codeproject.com/KB/aspnet/AspNetMVCandJqGrid.aspx).Botvinnik
@snmcdonald thank you for the link. I'll check it out. You should add this as an answer. Thanks.Fash
@Sergio I may be trying to he a little clever, but @snmcdonald explained a use for this that is applicable to my situation. I'm just trying to understand all options. Plus, seeing Guthrie blog about it increases my interest and makes me wonder if this is a tool to use. Thanks!Fash
See a demo at rule.codeeffects.com/Linq-to-Sql-Entity-Data-Filter-Demo, it does what you are looking forCandent
B
6

This feature would be really nice to have. A similar feature exists in ADO.net Datatables. It would be really helpful for LinqToSql as well. Sure you would lose strongly typed checking, but thats the whole point, you want dynamic searches. If you handle the exceptions properly I really think its a feature worth having.

You might consider adding a feature request to Microsoft Connect. The library already exists maybe they will consider adding official support for it. If you do make a feature request make sure you post a link here so we can vote for it. Microsoft Connect has voting system similar to stackoverflow. I have submitted a few myself LinqtoSql TableUpdate and VB.net Readonly Interfaces like C#.

I remember having some trouble with this library. I think it had something to do with static methods.

I found it better to develop the expressions I needed. This article by Ilya Builuk demonstrates custom expressions. The nice thing about Ilya's framework it removes a lot of the boilerplate code when doing operations like sorting for jqGrid.

I found it extremely helpful when learning about the underlying concepts of expressions.

The nice thing about this code is that it allows you to use dot operators for getters. Person.Age or if you want to violate Demeter you can even do multiple getters.

The code can be improved upon. I believe I added StartsWith and only allowed it for string operations as well as a few other search operations. Regardless its worth a look, it helped me understand linq expressions a lot.

public static IQueryable<T> Where<T>(this IQueryable<T> query, string column, object value, WhereOperation operation)
{
    if (string.IsNullOrEmpty(column))
        return query;

    ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

    MemberExpression memberAccess = null;
    foreach (var property in column.Split('.'))
        memberAccess = MemberExpression.Property
           (memberAccess ?? (parameter as Expression), property);

    //change param value type
    //necessary to getting bool from string
    ConstantExpression filter = Expression.Constant
        (
            Convert.ChangeType(value, memberAccess.Type)
        );

    //switch operation
    Expression condition = null;
    LambdaExpression lambda = null;
    switch (operation)
    {
        //equal ==
        case WhereOperation.Equal:
            condition = Expression.Equal(memberAccess, filter);
            lambda = Expression.Lambda(condition, parameter);
            break;
        //not equal !=
        case WhereOperation.NotEqual:
            condition = Expression.NotEqual(memberAccess, filter);
            lambda = Expression.Lambda(condition, parameter);
            break;
        //string.Contains()
        case WhereOperation.Contains:
            condition = Expression.Call(memberAccess,
                typeof(string).GetMethod("Contains"),
                Expression.Constant(value));
            lambda = Expression.Lambda(condition, parameter);
            break;
    }


    MethodCallExpression result = Expression.Call(
           typeof(Queryable), "Where",
           new[] { query.ElementType },
           query.Expression,
           lambda);

    return query.Provider.CreateQuery<T>(result);
}

WhereOperation enumerator:

public enum WhereOperation { Equal, NotEqual, Contains }
Botvinnik answered 3/3, 2011 at 0:45 Comment(0)
L
10

You may want to take a look at PredicateBuilder

Larisalarissa answered 2/3, 2011 at 4:4 Comment(2)
that's an interesting piece of code. I'm going to have to check it out. Thanks!Fash
I just tested it and it's not case-sensitive. Good work user295190.Aldo
B
6

This feature would be really nice to have. A similar feature exists in ADO.net Datatables. It would be really helpful for LinqToSql as well. Sure you would lose strongly typed checking, but thats the whole point, you want dynamic searches. If you handle the exceptions properly I really think its a feature worth having.

You might consider adding a feature request to Microsoft Connect. The library already exists maybe they will consider adding official support for it. If you do make a feature request make sure you post a link here so we can vote for it. Microsoft Connect has voting system similar to stackoverflow. I have submitted a few myself LinqtoSql TableUpdate and VB.net Readonly Interfaces like C#.

I remember having some trouble with this library. I think it had something to do with static methods.

I found it better to develop the expressions I needed. This article by Ilya Builuk demonstrates custom expressions. The nice thing about Ilya's framework it removes a lot of the boilerplate code when doing operations like sorting for jqGrid.

I found it extremely helpful when learning about the underlying concepts of expressions.

The nice thing about this code is that it allows you to use dot operators for getters. Person.Age or if you want to violate Demeter you can even do multiple getters.

The code can be improved upon. I believe I added StartsWith and only allowed it for string operations as well as a few other search operations. Regardless its worth a look, it helped me understand linq expressions a lot.

public static IQueryable<T> Where<T>(this IQueryable<T> query, string column, object value, WhereOperation operation)
{
    if (string.IsNullOrEmpty(column))
        return query;

    ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

    MemberExpression memberAccess = null;
    foreach (var property in column.Split('.'))
        memberAccess = MemberExpression.Property
           (memberAccess ?? (parameter as Expression), property);

    //change param value type
    //necessary to getting bool from string
    ConstantExpression filter = Expression.Constant
        (
            Convert.ChangeType(value, memberAccess.Type)
        );

    //switch operation
    Expression condition = null;
    LambdaExpression lambda = null;
    switch (operation)
    {
        //equal ==
        case WhereOperation.Equal:
            condition = Expression.Equal(memberAccess, filter);
            lambda = Expression.Lambda(condition, parameter);
            break;
        //not equal !=
        case WhereOperation.NotEqual:
            condition = Expression.NotEqual(memberAccess, filter);
            lambda = Expression.Lambda(condition, parameter);
            break;
        //string.Contains()
        case WhereOperation.Contains:
            condition = Expression.Call(memberAccess,
                typeof(string).GetMethod("Contains"),
                Expression.Constant(value));
            lambda = Expression.Lambda(condition, parameter);
            break;
    }


    MethodCallExpression result = Expression.Call(
           typeof(Queryable), "Where",
           new[] { query.ElementType },
           query.Expression,
           lambda);

    return query.Provider.CreateQuery<T>(result);
}

WhereOperation enumerator:

public enum WhereOperation { Equal, NotEqual, Contains }
Botvinnik answered 3/3, 2011 at 0:45 Comment(0)
C
5

It should now be available. I could download it through NuGet: http://www.nuget.org/packages/System.Linq.Dynamic/

Cabala answered 17/1, 2014 at 12:55 Comment(0)
M
1

I don't think it's "supported" by Microsoft - it seems to be released under a public license, which says in part:

(E) The software is licensed “as-is.” You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.

On your second question, I don't think there's a .NET 4 version. The 3.5 should work fine in a 4.0 project, and I don't think there's really much to add in. As I understand it, this was a nifty little library for doing those occasional, one-off string-based linq queries. Maybe you were for some reason manually sorting a grid, and needed to modify your collections sort order based on a string representing the property in question. Voila. I doubt you'll see a lot of effort put into adding a lot of features into this.

Miyokomizar answered 2/3, 2011 at 3:49 Comment(2)
Thanks @Adam. I didn't think it was supported - so thanks for the clarification. And the way you described how it could be used is how I'm thinking of using it.Fash
Yeah, I've used it similarly. I think it's the main reason for its existence. Good luck!Miyokomizar

© 2022 - 2024 — McMap. All rights reserved.