Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic where condition in LINQ

I have a scenario where I have to use a dynamic where condition in LINQ.

I want something like this:

public void test(bool flag)
{
   from e in employee
   where e.Field<string>("EmployeeName") == "Jhom"
   If (flag == true)
   {
       e.Field<string>("EmployeeDepartment") == "IT"
   }
   select e.Field<string>("EmployeeID")
}

I know we can't use the 'If' in the middle of the Linq query but what is the solution for this?

Please help...

like image 625
Shivi Avatar asked Apr 15 '11 09:04

Shivi


People also ask

What is dynamic LINQ C#?

The Dynamic LINQ library exposes a set of extension methods on IQueryable corresponding to the standard LINQ methods at Queryable, and which accept strings in a special syntax instead of expression trees.

What is Predicatebuilder C#?

Predicate Builder is a powerful LINQ expression that is mainly used when too many search filter parameters are used for querying data by writing dynamic query expression. We can write a query like Dynamic SQL. To learn more about predicate delegate visit Predicate Delegate.

Is Dynamic LINQ safe?

And Dynamic Linq is actually composed from strings, therefore it is potentially prone to attack by injection. Obviously, the attacker will have to be aware of the fact that you are using DynamicLinq and could attack only preparing the data so it results in valid malicious Dynamic Linq query.


3 Answers

Please check out the full blog post: Dynamic query with Linq

There are two options you can use:

Dynamic LINQ library

string condition = string.Empty;
if (!string.IsNullOrEmpty(txtName.Text))
    condition = string.Format("Name.StartsWith(\"{0}\")", txtName.Text);

EmployeeDataContext edb = new EmployeeDataContext();
if(condition != string.empty)
{
  var emp = edb.Employees.Where(condition);
 ///do the task you wnat
}
else
{
 //do the task you want 
}

Predicate Builder

Predicate builder works similar to Dynamic LINQ library but it is type safe:

var predicate = PredicateBuilder.True<Employee>();

if(!string.IsNullOrEmpty(txtAddress.Text))
    predicate = predicate.And(e1 => e1.Address.Contains(txtAddress.Text));

EmployeeDataContext edb= new EmployeeDataContext();
var emp = edb.Employees.Where(predicate);

difference between above library:

  • PredicateBuilder allows to build typesafe dynamic queries.
  • Dynamic LINQ library allows to build queries with dynamic Where and OrderBy clauses specified using strings.
like image 98
Pranay Rana Avatar answered Oct 02 '22 23:10

Pranay Rana


So, if flag is false you need all Jhoms, and if flag is true you need only the Jhoms in the IT department

This condition

!flag || (e.Field<string>("EmployeeDepartment") == "IT"

satisfies that criterion (it's always true if flag is false, etc..), so the query will become:

from e in employee    
where e.Field<string>("EmployeeName") == "Jhom"
  && (!flag || (e.Field<string>("EmployeeDepartment") == "IT")
select e.Field<string>("EmployeeID") 

also, this e.Field<string>("EmployeeID") business, smells like softcoding, might take a look into that. I guess

from e in employee    
where e.EmployeeName == "Jhom"
  && (!flag || (e.EmployeeDepartment == "IT")
select e.EmployeeID

would be more compact and less prone to typing errors.


EDIT: This answer works for this particular scenario. If you have lots of this kinds of queries, by all means investingate the patterns proposed in the other answers.

like image 39
SWeko Avatar answered Oct 03 '22 00:10

SWeko


You can chain methods :

public void test(bool flag)
{
   var res = employee.Where( x => x.EmployeeName = "Jhom" );

   if (flag)
   {
       res = res.Where( x => x.EmployeeDepartment == "IT")
   }

   var id = res.Select(x => x.EmployeeID );
}
like image 31
mathieu Avatar answered Oct 03 '22 00:10

mathieu