Как реализовать динамическое предложение "where" в LINQ?
Я хочу иметь динамическое условие where
.
В следующем примере:
var opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations
on opp.OrganizationID equals org.OrgnizationID
where opp.Title.StartsWith(title)
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
Несколько раз у меня Title
, а иногда я этого не делаю. А также я хочу добавить дату в выражении where
динамически.
Например, как этот SQL:
string whereClause;
string SQL = whereClause == string.Empty ?
"Select * from someTable" : "Select * from someTable" + whereclause
Ответы
Ответ 1
Вы можете переписать его следующим образом:
var opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations on opp.OrganizationID equals org.OrgnizationID
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
if(condition)
{
opportunites = opportunites.Where(opp => opp.Title.StartsWith(title));
}
РЕДАКТИРОВАТЬ: Чтобы ответить на ваш вопрос в комментариях, да, вы можете сохранить добавление к исходному Queryable. Помните, что это все лениво выполнено, поэтому на этом этапе все это делает это, создавая IQueryable, чтобы вы могли связывать их вместе по мере необходимости:
if(!String.IsNullOrEmpty(title))
{
opportunites = opportunites.Where(.....);
}
if(!String.IsNullOrEmpty(name))
{
opportunites = opportunites.Where(.....);
}
Ответ 2
Вы можете динамически добавлять предложение where к вашему выражению IQueryable следующим образом:
var finalQuery = opportunities.Where( x => x.Title == title );
и для даты аналогично.
Однако вам придется подождать, чтобы создать анонимный тип, пока после того, как вы закончите динамически добавлять свои предложения where , если, ваш анонимный тип не содержит полей, которые вы хотите запросить в своем где предложение.
Итак, у вас может быть что-то похожее на это:
var opportunities = from opp in oppDC.Opportunities
join org in oppDC.Organizations on
opp.OrganizationID equals org.OrgnizationID
select opp
if(!String.IsNullOrEmpty(title))
{
opportunities = opportunities.Where(opp => opp.Title == title);
}
//do the same thing for the date
opportunities = from opp in opportunities
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
Ответ 3
Предложение WHERE может быть сделано как
//...
where string.IsNullOrEmpty(title) ? true : opp.Title.StartsWith(title)
//...
Динамическое возвращение записей, которые я не думаю, возможно в LINQ, так как он должен иметь возможность создавать последовательный анонимный тип (в фоновом режиме)
Ответ 4
Поскольку запросы являются составными, вы можете просто построить запрос пошагово.
var query = table.Selec(row => row.Foo);
if (someCondition)
{
query = query.Where(item => anotherCondition(item));
}
Ответ 5
В следующих вопросах и ответах это довольно хорошо:
Динамическое предложение where в LINQ - с именами столбцов, доступными во время выполнения
Есть ли шаблон, использующий Linq для динамического создания фильтра?
Ответ 6
Если вы знаете заранее все возможное, когда запросы, подобные приведенному в примере SQL, вы можете написать запрос, подобный этому
from item in Items
where param == null ? true : ni.Prop == param
select item;
если вы не знаете все возможное, где предложения заранее, вы можете добавить, где dymically, например, вот так:
query = query.Where(item => item.ID != param);
Ответ 7
Я искал создание предложения dynamic where в LINQ и натолкнулся на очень красивое решение в Интернете, которое использует ExpressionBuilder в С#.
Я размещаю его здесь, так как ни одно из вышеупомянутых решений не использует этот подход. Это помогло мне. Надеюсь, это тоже поможет
http://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq
Ответ 8
Используйте это:
bool DontUseTitles = true; // (Or set to false...
var opportunites = from opp in oppDC.Opportunities
join org in oppDC.Organizations
on opp.OrganizationID equals org.OrgnizationID
where (DontUseTitles | opp.Title.StartsWith(title))
select new
{
opp.OpportunityID,
opp.Title,
opp.PostedBy,
opp.Address1,
opp.CreatedDate,
org.OrganizationName
};
Почему это работает? Если DontUseTitles истинно, он выбирает все, потому что "(DontUseTitles | opp.Title.StartsWith(название))" оценивается как true. В противном случае он использует второе условие и просто возвращает подмножество.
Почему каждый всегда делает вещи более сложными, чем они должны быть?: -)