C# DynamicLinq where clause with Any()
Asked Answered
P

5

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.

Plasia answered 10/6, 2016 at 5:18 Comment(5)
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 ?Sweetmeat
You can use Expression for this. Probably you need some builder to build your string query to Expression tree.Blithesome
What is the version of EF you are using?Broderic
I'm using Telerik DataAccess 2015.1.225.1Plasia
There is library for dynamic linq weblogs.asp.net/scottgu/…Radian
H
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\")");
Hoes answered 10/6, 2016 at 6:1 Comment(0)
S
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.

Sweetmeat answered 10/6, 2016 at 5:40 Comment(0)
E
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'

Enjambement answered 10/6, 2016 at 5:22 Comment(0)
D
1

You need something like this :

query =  db.Customers.Where(x => x.Categories.Where(y => y.Code == "Retail").Any());
Dose answered 10/6, 2016 at 5:23 Comment(6)
I need where clause be string.Plasia
@Plasia for what reason?Dose
Because it's not predefined, clause will be generated on runtime.Plasia
Why is it generated at runtime? if there's options why not just have different quires to be run depending on the optionsHickerson
@Plasia i doubt it would be possible as far as i know, you can only pass strings for expressions but for API functions as part of the string, I never encountered cases like thatDose
Cause it should work in big project with large number of entities and options.Plasia
M
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)
Monica answered 10/6, 2016 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.