Я создаю создание приложения, которое ищет базу данных и позволяет пользователю динамически добавлять какие-либо критерии (возможно, около 50), так же как следующий вопрос SO: Создание динамических запросов с помощью структура сущностей. В настоящее время я работаю над поиском, который проверяет каждый критерий, и если он не пуст, он добавляет его в запрос.
С#
var query = Db.Names.AsQueryable();
if (!string.IsNullOrWhiteSpace(first))
query = query.Where(q => q.first.Contains(first));
if (!string.IsNullOrWhiteSpace(last))
query = query.Where(q => q.last.Contains(last));
//.. around 50 additional criteria
return query.ToList();
Этот код создает что-то похожее на следующее в sql-сервере (я упрощен для более простого понимания)
SQL
SELECT
[Id],
[FirstName],
[LastName],
...etc
FROM [dbo].[Names]
WHERE [FirstName] LIKE '%first%'
AND [LastName] LIKE '%last%'
Теперь я пытаюсь добавить способ сгенерировать следующий SQL с С# через сущность framework, но с OR вместо AND, сохраняя при этом возможность динамически добавлять критерии.
SQL
SELECT
[Id],
[FirstName],
[LastName],
...etc
FROM [dbo].[Names]
WHERE [FirstName] LIKE '%first%'
OR [LastName] LIKE '%last%' <-- NOTICE THE "OR"
Обычно критерии не будут превышать два или три элемента для запроса, но объединение их в один гигантский запрос не является вариантом. Я пробовал concat, union и пересекаюсь, и они просто дублируют запрос и присоединяют их к UNION.
Есть ли простой и чистый способ добавить условия "ИЛИ" к динамически сгенерированному запросу с использованием сущности framework?
Изменить с помощью моего решения - 9/29/2015
После публикации этого вопроса я заметил, что это привлекло небольшое внимание, поэтому я решил опубликовать свое решение
// Make sure to add required nuget
// PM> Install-Package LinqKit
var searchCriteria = new
{
FirstName = "sha",
LastName = "hill",
Address = string.Empty,
Dob = (DateTime?)new DateTime(1970, 1, 1),
MaritalStatus = "S",
HireDate = (DateTime?)null,
LoginId = string.Empty,
};
var predicate = PredicateBuilder.False<Person>();
if (!string.IsNullOrWhiteSpace(searchCriteria.FirstName))
{
predicate = predicate.Or(p => p.FirstName.Contains(searchCriteria.FirstName));
}
if (!string.IsNullOrWhiteSpace(searchCriteria.LastName))
{
predicate = predicate.Or(p => p.LastName.Contains(searchCriteria.LastName));
}
// Quite a few more conditions...
foreach(var person in this.Persons.Where(predicate.Compile()))
{
Console.WriteLine("First: {0} Last: {1}", person.FirstName, person.LastName);
}