Generic LINQ query predicate?

33,052

Solution 1

It sounds like you're looking for Dynamic Linq. Take a look here. This allows you to pass strings as arguments to the query methods, like:

var query = dataSource.Where("CategoryID == 2 && UnitPrice > 3")
                      .OrderBy("SupplierID");

Edit: Another set of posts on this subject, using C# 4's Dynamic support: Part 1 and Part 2.

Solution 2

What it sounds like is you want basically a conditional predicate builder..

I hope you can mold this into something you are looking for, good luck!

http://www.albahari.com/nutshell/predicatebuilder.aspx

Solution 3

You might want to look at expression trees:

IQueryable<T> getQuery<T>(T myTableEntity, string[] arrayOfQueryTerms, Expression<Func<T, bool>> predicate)
 { var fieldOrProperty = getMemberInfo(predicate);
   /* ... */
 }

MemberInfo getmemberInfo<T>(Expression<Func<T,bool> expr)
 { var memberExpr = expr as MemberExpression;
   if (memberExpr != null) return memberExpr.Member;
   throw new ArgumentException();
 }

var q = getQuery<FooTable>(foo, new[]{"Bar","Baz"}, x=>x.FieldName);
Share:
33,052

Related videos on Youtube

Codewerks
Author by

Codewerks

[email protected]

Updated on September 19, 2021

Comments

  • Codewerks
    Codewerks over 2 years

    Not sure if this is possible or if I'm expressing correctly what I'm looking for, but I have the following piece of code in my library repeatedly and would like to practice some DRY. I have set of SQL Server tables that I'm querying based on a simple user-supplied search field ala Google. I'm using LINQ to compose the final query based on what's in the search string. I'm looking for a way to use generics and passed in lambda functions to create a reusable routine out of this:

    string[] arrayOfQueryTerms = getsTheArray();
    
    var somequery = from q in dataContext.MyTable
                    select q;
    
    if (arrayOfQueryTerms.Length == 1)
    {
        somequery = somequery.Where<MyTableEntity>(
            e => e.FieldName.StartsWith(arrayOfQueryTerms[0]));
    }
    else
    {
        foreach(string queryTerm in arrayOfQueryTerms)
        {
            if (!String.IsNullOrEmpty(queryTerm))
            {
                somequery = somequery 
                            .Where<MyTableEntity>(
                                e => e.FieldName.Contains(queryTerm));
            }
        }
    }
    

    I was hoping to create a generic method with signature that looks something like:

    private IQueryable<T> getQuery(
        T MyTableEntity, string[] arrayOfQueryTerms, Func<T, bool> predicate)
    

    I'm using the same search strategy across all my tables, so the only thing that really differs from usage to usage is the MyTable & MyTableEntity searched and the FieldName searched. Does this make sense? Is there a way with LINQ to dynamically pass in the name of the field to query in the where clause? Or can I pass in this as a predicate lambda?

    e => e.FieldName.Contains(queryTerm)
    

    I realize there a million and a half ways to do this in SQL, probably easier, but I'd love to keep everything in the LINQ family for this one. Also, I feel that generics should be handy for a problem like this. Any ideas?

  • Codewerks
    Codewerks over 15 years
    I think the Dynamic LINQ answer is what I'm going to go with, but thanks for this, I will also try and work through this tomorrow.
  • Codewerks
    Codewerks over 15 years
    Thanks! Very cool, I need to look through all of ScottGu's blog posts on this topic...
  • Erik Forbes
    Erik Forbes over 15 years
    Unfortunately I've only found the one - I thought he had a series but I guess I was wrong. There are other sources of information though.
  • Thomas
    Thomas over 9 years
    sorry to ask one question here. what is predicate and how it is related to linq?
  • Erik Forbes
    Erik Forbes over 9 years
    A predicate is an expression that evaluates to a bool. Predicates are used as arguments to Where clauses in LINQ expressions. In the example above, CategoryID == 2 && UnitPrice > 3 is a predicate.
  • AliReza Sabouri
    AliReza Sabouri over 2 years
    I think Gridify is a better alternative. github.com/alirezanet/Gridify
  • Erik Forbes
    Erik Forbes over 2 years
    @AliReza I'll check it out. =)