我正试图使用LINQ和Entity框架在我的应用程序中构建一个高级搜索,该框架依赖于10个参数,但用户可以发送一个或多个参数进行搜索。我很想用下面的方式实现它,但它没有起作用,而是设置if条件并在每次检查时更改查询。
那么,有没有什么简单的方法可以使用LINQ根据用户输入进行选择,以匹配存在的结果?
var data = (from item in db.Student
where item.Firstname == fname
&& item.Middlename == mname
&& item.Lastname == lname
&& item.Birthday == birthday
&& item.Age == age
&& item.AdmissionYear == year
&& item.Grade == grade
&& item.Address == Address
&& item.Class == class
&& item.Number == number
select item).FirstOrDefault();
实现这一点的简单方法是使用形式的where子句链接。与表达式树相比,我一直更喜欢这种方法,因为它简单明了。
假设所有谓词值都可以为null,下面是一个示例:
var query = db.Student.AsQueryable();
if (age != null)
query = query.Where(s => s.Age == age.Value);
if (fname != null)
query = query.Where(s => s.Firstname == fname);
if (lname != null)
query = query.Where(s => s.Lastname == lname);
// etc...
var student = query.FirstOrDefault();
通过这种方式,您可以只使用用户传入的属性动态构建where子句,而忽略其余属性
您还可以在新的Filter对象中定义所有参数,并将这些"if"语句提取到自己的FilterStudents方法中,该方法采用IQueryable<学生>和筛选作为参数。
您可以使用并构建一个表达式树,它将根据您传递的参数动态构建筛选子句
一篇简单的文章,这里有一个例子
http://www.codeproject.com/Tips/582450/Build-Where-Clause-Dynamically-in-Linq
您也可以使用PredicateBuilder
类
http://www.albahari.com/nutshell/predicatebuilder.aspx
所以你会有这样的
IQueryable<Product> SearchProducts (params string[] keywords)
{
var predicate = PredicateBuilder.False<Product>();
foreach (string keyword in keywords)
{
string temp = keyword;
predicate = predicate.Or(p => p.Description.Contains (temp));
}
return dataContext.Products.Where (predicate);
}
我不确定"simple",但是的,这是可能的。
这里的主要思想是为QueryAble.Where()方法创建一个表达式树。
public class SearchedTerms
{
public string FirstName {get;set;}
...
public int Age {get;set;}
}
public Expression<Func<Student,bool>> GetPredicateExpression(SearchedTerms terms)
{
// ...
}