我正在创建一个应用程序,用于搜索数据库并允许用户动态添加任何条件(大约有50个可能条件),就像以下SO问题:Creating dynamic queries with entity framework。 我目前已经实现了一个检查每个条件的搜索功能,如果条件不为空,则将其添加到查询中。
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();
这段代码在 SQL Server 中会生成类似于以下内容的结果(为了更易理解,我进行了简化)
SQL
SELECT
[Id],
[FirstName],
[LastName],
...etc
FROM [dbo].[Names]
WHERE [FirstName] LIKE '%first%'
AND [LastName] LIKE '%last%'
我现在正在尝试通过实体框架和C#生成以下SQL,并用OR代替AND,同时仍然保持动态添加条件的能力。
SQL
SELECT
[Id],
[FirstName],
[LastName],
...etc
FROM [dbo].[Names]
WHERE [FirstName] LIKE '%first%'
OR [LastName] LIKE '%last%' <-- NOTICE THE "OR"
通常一个查询的标准不会超过两三个,但将它们合并成一个巨大的查询不是一个选择。我尝试过使用concat、union和intersect,但它们只是复制了查询并用UNION连接它们。
有没有一种简单清晰的方法,可以使用实体框架为动态生成的查询添加“OR”条件?
编辑我的解决方案-2015年9月29日
自从发布这篇文章以来,我注意到它引起了一些关注,所以我决定发布我的解决方案
// 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);
}