Dynamic where condition in LINQ - c#

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

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.

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.

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 );
}

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

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"));
}

Related

Conditional Where in Linq using query syntax

Is there a better way to have conditional where clauses in LINQ equivalent to the following?
var doGroup=false;
var doSub=true;
var query= from mydata in Data_Details
where
((doGroup && mydata.Group == "xxxx") || (doGroup==false)) &&
((doSub && mydata.SubGroup == "yyyy") || (doSub==false))
select mydata;
In the code above that works it will optionally include 'Group' and 'SubGroup' depending on whether doGroup and doSub are true are false.
I know when using method syntax you can simply keep appending code to the query in separate lines but I'd prefer to keep using query syntax.
The easiest way to make this smaller is by optimizing the conditions themselves:
var doGroup=false;
var doSub=true;
var query=from mydata in Data_Details
where
(!doGroup || mydata.Group == "xxxx") &&
(!doSub || mydata.SubGroup == "yyyy")
select mydata;
You can write an extension method:
public static IQueryable<T> WhereIf<T>(
this IQueryable<T> source, bool condition,
Expression<Func<T, bool>> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
Usage:
var doGroup =false;
var doSub = true;
var query = Data_Details
.WhereIf(doGroup, q => q.Group == "xxxx")
.WhereIf(doSub, e => e.SubGroup == "yyyy")
Ruud Kobes answer is the right one,
a small point at which there is not need to project data,
last select is not needed.
var doGroup=false;
var doSub=true;
var query=from mydata in Data_Details
where
(!doGroup || mydata.Group == "xxxx") &&
(!doSub || mydata.SubGroup == "yyyy");

how to generate where condition without multiple if condition using linq query

I have 3 search textbox values. i need to check string.isnullorEmpty for each variable and have to compare with the linq query.
My Text Values:
Manufacturer
Project Code
PartNo
Conditions:
if i search any one of the above i should get the result
If i enter 3 box values i should get the result
If i enter any 2 then i should get result.
My code as follows
if (!string.IsNullOrEmpty(manufacturer))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.Manufacturer == manufacturer);
}
if (!string.IsNullOrEmpty(projectcode))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.ProjectCode== projectcode);
}
if (!string.IsNullOrEmpty(part))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.Part== part);
}
To avoid multiple conditions how to make dynamic where clause for this? Please find out the solution for this..
He wants to get rid of the if statements and write this all as a linq query. I think you want something like this
.Where(
s =>
(string.IsNullOrEmpty(manufacturer) | (s.Manufacturer == manufacturer)) &&
(string.IsNullOrEmpty(projectcode) | (s.ProjectCode == projectcode)) &&
(string.IsNullOrEmpty(part) | (s.Part== part))
).ToList();
You can just tag on multiple Where clauses
var filteredResult = _entity.MaterialMasters;
if (!string.IsNullOrEmpty(manufacturer))
filteredResult = filteredResult.Where(x => x.Manufacturer == manufacturer);
}
if (!string.IsNullOrEmpty(projectcode))
filteredResult = filteredResult.Where(x => x.ProjectCode == projectcode);
}
if (!string.IsNullOrEmpty(part))
filteredResult = filteredResult.Where(x => x.Part == part);
}
They will work cumulatively, meaning that you can supply 1, 2 or 3 of the parameters and you'll get the appropriate results.
var filteredResult =
_entity.Where(
ent =>
(!string.IsNullOrEmpty(manufacturer) && ent.Manufacturer == manufacturer)
|| (!string.IsNullOrEmpty(projectcode) && ent.ProjectCode == projectcode)
|| (!string.IsNullOrEmpty(part) && ent.Part == part));
This will get you any result for manufacturer, projectCode and part in one place.

Construct LINQ query using variables in asp.net WebAPI

I am trying to build a method in my asp.net WebAPI to grab data based on the arguments passed on the method. The method is used to perform a search on restaurant data. I have a variable called 'type' that determines the type of data search performed. The second variable 'keyword' is the keyword searched by the user. The WHERE condition in my LINQ query depends on the type and needs to be dynamic, so I have used a separate variable outside the LINQ query to define the condition. I have tried assigning this variable to my WHERE statement on the LINQ query but it doesn't seem to work. Can someone help with it please? I have been stuck on this for a few days now
public IQueryable<RestaurantView> GetRestaurantsForSearch(string keyword, int type, string location)
{
//
var condition = "";
if(type == 1)
{
condition = "x.RestaurantName.Contains(keyword)";
} else if(type == 2){
condition = "x.Cuisine.Equals(keyword)";
}
else {
condition = "x.Rating.Equals(keyword)";
}
var query = from x in db.Restaurants
join y in db.Cuisine on x.RestaurantCuisine equals y.CuisineID
where condition
select new RestaurantView
{
RestaurantID = x.RestaurantID,
RestaurantName = x.RestaurantName,
RestaurantCuisine = y.CuisineName,
RestaurantDecription = x.RestaurantDecription
};
return query;
}
Try this:
Predicate<Restaurant> pred;
if (type == 1) pred = x => x.RestaurantName.Contains(keyword);
else if (type == 2) pred = x => x.Cuisine.Equals(keyword);
else pred = x => x.Rating.Equals(keyword);
var query = from x in db.Restaurants
join y in db.Cuisine on x.RestaurantCuisine equals y.CuisineID
where pred(x)
select new RestaurantView
{
RestaurantID = x.RestaurantID,
RestaurantName = x.RestaurantName,
RestaurantCuisine = y.CuisineName,
RestaurantDecription = x.RestaurantDecription
};
return query;
You need to look a dynamic linq library i think then you can execute string statements inside your linq
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
or you can execute direct query
http://msdn.microsoft.com/en-us/library/system.data.linq.datacontext.executequery.aspx
If you are ok with dropping your comprehensive LINQ query in favour of the extension method syntax, it's pretty simple (I'm on a netbook without VS, so I apologize that this is untested but should give you the idea):
var query = db.Restaurants
.Include("Cuisine")
if(type == 1)
{
query= query.Where(x => x.RestaurantName.Contains(keyword));
}
else if(type == 2)
{
query = query.Where(x => x.Cuisine == keyword);
}
else {
query = query.Where(x => x.Rating == keyword);
}
This builds out your expression tree differently based on your logic checks, which will result in a different SQL query being generated based on the value of type.
I notice that in your join, Cuisine appears to be an Entity, but in your logic checks, you attempt to filter by comparing Cuisine to a string so I think there is some disconnect.
var query = from x in db.Restaurants
join y in db.Cuisine on x.RestaurantCuisine equals y.CuisineID
where condition
select new RestaurantView
{
RestaurantID = x.RestaurantID,
RestaurantName = x.RestaurantName,
RestaurantCuisine = y.CuisineName,
RestaurantDecription = x.RestaurantDecription
};
return query;
}
how to get the return query value in client side to assign for grid view binding

Linq: how to exclude condition if parameter is null

I have some table and the following condition of query: if parameter A is null take all, if not, use it in the query. I know how to do that in 2 steps:
List<O> list = null;
if (A = null)
{
list = context.Obj.Select(o => o).ToList();
}
else
{
list = context.Obj.Where(o.A == A).ToList();
}
Is it possible to have the same as one query?
Thanks
How about:
list = context.Obj.Where(o => A == null || o.A == A)
.ToList();
You can do it in one query but still using a condition:
IEnumerable<O> query = context.Obj;
if (A != null)
{
query = query.Where(o => o.A == A);
}
var list = query.ToList();
Or you could use a conditional operator to put the query in a single statement:
var query = A is null ? context.Obj : context.Obj.Where(o => o.A == A);
var list = query.ToList();
I would personally suggest either of the latter options, as they don't require that the LINQ provider is able to optimise away the filter in the case where A is null. (I'd expect most good LINQ providers / databases to be able to do that, but I'd generally avoid specifying a filter when it's not needed.)
I opted for
var list = context.Obj.Where(o => A.HasValue ? o.a == A : true);
I would probably write the query like this:
IQueryable<O> query = context.Obj;
if (A != null)
query = query.Where(o => o.A == A);
var list = query.ToList()
It's not one expression, but I think it's quite readable.
Also, this code assumes that context.Obj is IQueryable<O> (e.g. you are using LINQ to SQL). If that's not the case, just use IEnumerable<O>.

Linq to Entity - How to concatenate conditions

I am writing a Linq Query. Is there a way that I can concatenate to query based on some if conditions?
Like on query is
from res in _db.Person
where res.Departments.ID == deptId
select res;
And if I have a condition true, I would like it to be something like
from res in _db.Person
where res.Departments.ID == deptId && res.Departments.Type == deptType
select res;
Implementing an "AND" type condition is easy - and easier using extension method syntax to call Where multiple times:
IQueryable<Person> people = _db.Person
.Where(res => res.Departments.ID == deptId);
if (deptType != null)
{
people = people.Where(res => res.Departments.Type == deptType);
}
// Potentially add projections etc.
EDIT: If you want "OR" functionality, it's slightly tricky from scratch, as you need to mess around with expression trees. I suggest you use the PredicateBuilder library:
Expression<Func<Person, bool> predicate = res => res.Departments.ID == deptId;
if (deptType != null)
{
predicate = predicate.Or(res => res.Departments.Type == deptType);
}
IQueryable<Person> people = _db.Person.Where(predicate);
Assuming your condition is in the variable condition
from res in _db.Person
where res.Departments.ID == deptId && (!condition || res.Departments.Type == deptType)
select res;
Version that does or as requested
from res in _db.Person
where res.Departments.ID == deptId || (condition && res.Departments.Type == deptType))
select res;
Alternatively you may wish to use predicate builder
I would do something like this:
var result = _db.Person.Where(x=>x.Departments.ID == deptId);
if(myCondition)
result = result.Where(x=>x.Departments.Type == deptType);
The query is not actually executed until you attempt to enumerate result, so you can keep adding conditions as long as you like.

Categories

Resources