I am creating an application that searches the database and allows the user to dynamically add any criteria (around 50 possible), much like the following SO question: Creating dynamic queries with entity framework. I currently have working a search that checks each criteria, and if it is not blank it adds it to the query.
C#
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();
This code produces something similar to the following in sql server (I simplified for easier understanding)
SQL
SELECT
[Id],
[FirstName],
[LastName],
...etc
FROM [dbo].[Names]
WHERE [FirstName] LIKE '%first%'
AND [LastName] LIKE '%last%'
I am now trying to add a way to generate the following SQL with C# through entity framework but with an OR instead of an AND, while still keeping the ability to add criteria dynamically.
SQL
SELECT
[Id],
[FirstName],
[LastName],
...etc
FROM [dbo].[Names]
WHERE [FirstName] LIKE '%first%'
OR [LastName] LIKE '%last%' <-- NOTICE THE "OR"
Usually the criteria wont be larger than two or three items for a query but combining them into one gigantic query is not an option. I have tried concat, union, and intersect and they just all duplicate the query and join them with UNION.
Is there a simple and clean way to add "OR" conditions to a dynamically generated query using entity framework?
Edit with my solution - 9/29/2015
Since posting this, I have noticed this has received a little attention, so I decided to post my solution
// 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);
}
See Question&Answers more detail:
os