Dynamic where condition in LINQ
Asked Answered
H

5

11

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...

Hilbert answered 15/4, 2011 at 9:11 Comment(1)
It is not really dynamic, all you need to do is to call LINQ methods explicitly and chain them based on a condition.Modernistic
S
9

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.

Spherule answered 15/4, 2011 at 9:16 Comment(1)
This is the most straight forward.Bise
V
12

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.
Victualer answered 15/4, 2011 at 9:14 Comment(2)
First example seems to be taken off the context. What's the point of checking condition for emptiness if it has just been assigned string.Empty? I'll correct this now..Modernistic
@gaearon - if there are more no of condition thats y i put there ...i alreay posted link of full post where you can see detailVictualer
S
9

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.

Spherule answered 15/4, 2011 at 9:16 Comment(1)
This is the most straight forward.Bise
R
2

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 );
}
Randell answered 15/4, 2011 at 9:15 Comment(3)
I don't understand why the downvote ? Maybe an explanation could help me improve my answer ?Randell
I believe this is not what is being asked. The issue is not unknown property name but unknown (may I call it so) ‘chainity’. Your answer does not reflect how exactly you can chain queries with Dynamic LINQ. More to that, your example is wrong because EmployeeName is not Employee's property, it is a string passed to Field method.Modernistic
And, last but probably main reason for downvote, is my subjective opinion that this is a bad idea. The question does not call for Dynamic LINQ, all that is needed is arbitrary chaining, which is already possible using explicit LINQ method calls. Dynamic and not typesafe code must only be introduced where it's hard to achieve the same with type safety (e.g. user entering complicated expression right in search box). Dynamic LINQ is better than parsing but much worse than typesafe query which is very possible and even desirable with this question.Modernistic
C
0
from e in employee    
where e.Field<string>("EmployeeName") == "Jhom" &&
(!flag || e.Field<string>("EmployeeDepartment") == "IT")
select e.Field<string>("EmployeeID") 
Conserve answered 15/4, 2011 at 9:16 Comment(0)
M
0

You can call LINQ methods explicitly and chain them conditionally.

public IEnumerable<string> FilterEmployees (IEnumerable<Employee> source, bool restrictDepartment)
{
    var query = source.Where (e => e.Field<string>("EmployeeName") == "Jhom");

    if (restrictDepartment) // btw, there's no need for "== true"
        query = query.Where (e => e.Field<string>("EmployeeDepartment") == "IT");

    return query.Select (e => e.Field<string>("EmployeeID"));
}
Modernistic answered 15/4, 2011 at 9:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.