6

I want to run dynamic linq with a string where clause like this:

query = db.Customers.Where("Categories.Any(Code == 'Retail')");

Customer entity has collection of categories

class Customer
{
    public List<Category> Categories {get;set;}
    ...
}

class Category
{
    public Guid Id {get;set;}
    public string Code {get;set;}
}

Can anyone please tell me is it possible to do something like this?

PS: I need where clause be string. The where clause will be generated at runtime, for this reason I can't use Linq query expression.

I'm using Telerik DataAccess.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Daler
  • 814
  • 14
  • 28
  • What are the possible variations of the dynamic clause, do you mean the Code is not fixed or the whole condition ? Can you give couple of more different examples ? – Zein Makki Jun 10 '16 at 05:33
  • 1
    You can use [`Expression`](https://msdn.microsoft.com/en-us/library/ms173144.aspx) for this. Probably you need some builder to build your string query to Expression tree. – Ankush Madankar Jun 10 '16 at 05:36
  • What is the version of EF you are using? – Hamed Jun 10 '16 at 05:42
  • I'm using Telerik DataAccess 2015.1.225.1 – Daler Jun 10 '16 at 06:19
  • There is library for dynamic linq http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library – Eldho Jun 10 '16 at 06:30

5 Answers5

6

It's possible as soon as you follow the Expression Language rules.

For instance, string literals must be enclosed in double quotes:

query = db.Customers.Where("Categories.Any(Code == \"Retail\")");
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
2

You can build your own runtime Expression:

Expression<Func<Customer, bool>> myRuntimeExpression = null;

if(condition1)
{
    myRuntimeExpression = cust => cust.Categories.Any(cat => cat.Code == "Retial"); // or some local variable
}
else if(condition2)
{
    myRuntimeExpression = cust => cust.Categories.Any(cat => cat.Id = someId) == false;
}
else if(condition3)
{

}

var query = DB.Customers.Where(myRuntimeExpression);

However, if you need to build more complex queries have a look at Dynamic Queries in Linq Using Expressions.

Zein Makki
  • 29,485
  • 6
  • 52
  • 63
1

Shouldn't it be like below?

refinedCustomerList = db.Customers.Where(customer => customer.Categories.Any(Code == 'Retail'));

The above list will contain all the customers whose category is 'Retail'

h-rai
  • 3,636
  • 6
  • 52
  • 76
1

You need something like this :

query =  db.Customers.Where(x => x.Categories.Where(y => y.Code == "Retail").Any());
Anonymous Duck
  • 2,942
  • 1
  • 12
  • 35
1

The linq extention method were accepted an argument of type System.Func<TSource, Int32, Boolean>

  • In your case a Func that recieves a Customer as an argument and returns true / false.
    The result of the Where function would be all the Customers that the Func returned true for.

"Categories.Any(Code == 'Retail')" is a string, not a Func, thus cannot be passed as an argument to the Where method.

Perhaps what you are looking for, if you want to keep the query flexible is some thing like:

Public Customer[] QueryCustomers(Func<Customer,bool> predicate)
{
    var result =  db.Customers.Where(c=> predicate(c)).ToArray();
    return result;
}

Usage:

var retailCustomers =
      QueryCustomers(customer => customer.Categories.Any(Code == 'Retail'))   

Or any other query you might compose in run/compile time:

var customersWithNoCategories =
      QueryCustomers(customer => customer.Categories.Count == 0)
Avi Turner
  • 10,234
  • 7
  • 48
  • 75