Динамическое условие where в LINQ
У меня есть сценарий, где я должен использовать динамическое условие, в котором есть условие в LINQ.
Мне нужно что-то вроде этого:
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")
}
Я знаю, что мы не можем использовать "If" в середине запроса Linq, но каково решение для этого?
Пожалуйста, помогите...
Ответы
Ответ 1
Итак, если flag
- false
, вам нужны все Jhoms, и если flag
true, вам нужны только Jhoms в ИТ-отделе
Это условие
!flag || (e.Field<string>("EmployeeDepartment") == "IT"
удовлетворяет этому критерию (он всегда истинен, если флаг является ложным и т.д.), поэтому запрос будет выглядеть следующим образом:
from e in employee
where e.Field<string>("EmployeeName") == "Jhom"
&& (!flag || (e.Field<string>("EmployeeDepartment") == "IT")
select e.Field<string>("EmployeeID")
этот бизнес e.Field<string>("EmployeeID")
, пахнет как softcoding, может заглянуть в него. Думаю,
from e in employee
where e.EmployeeName == "Jhom"
&& (!flag || (e.EmployeeDepartment == "IT")
select e.EmployeeID
будет более компактным и менее подверженным ошибкам ввода.
EDIT: этот ответ работает на этот конкретный сценарий. Если у вас есть много таких запросов, обязательно инвестируйте шаблоны, предложенные в других ответах.
Ответ 2
Пожалуйста, просмотрите полное сообщение в блоге: Динамический запрос с Linq
Есть два варианта, которые вы можете использовать:
Динамическая библиотека LINQ
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 работает аналогично динамической библиотеке LINQ, но безопасен по типу:
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);
разница между вышеуказанной библиотекой:
- PredicateBuilder позволяет создавать динамические запросы типов.
- Библиотека Dynamic LINQ позволяет создавать запросы с динамическими предложениями Where и OrderBy, заданными с помощью строк.
Ответ 3
Вы можете цеплять методы:
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 );
}
Ответ 4
from e in employee
where e.Field<string>("EmployeeName") == "Jhom" &&
(!flag || e.Field<string>("EmployeeDepartment") == "IT")
select e.Field<string>("EmployeeID")
Ответ 5
Вы можете вызвать методы LINQ явно и связать их условно.
public IEnumerable<string> FilterEmployees (IEnumerable<Employee> source, bool restrictDepartment)
{
var query = source.Where (e => e.Field<string>("EmployeeName") == "Jhom");
if (restrictDepartment) // btw, there no need for "== true"
query = query.Where (e => e.Field<string>("EmployeeDepartment") == "IT");
return query.Select (e => e.Field<string>("EmployeeID"));
}