我有麻烦,能够使用表达式树复制多个.Wheres在我的LINQ查询,我需要这个查询是动态的,因为它的搜索feature.The数据库中,我将最终被查询将获得大量,所以我需要的效率和斜面筛选客户端。我至少想通过过滤这些列3开始。下面我添加了三个id的即时通讯试图通过筛选。我有很多读入表达式树,但可以使用某人的帮助,把它们真正应用到什么即时通讯做,因为他们混淆了我。
public int? heightId { get; set; }
public int? ageId { get; set; }
public int? genderId { get; set; }
这不是动态的,因为你事先知道的列。你并不需要使用表达式目录树为好。你可以只应用过滤器条件:
public Class[] FindByFilter(int limit, int? heightId = null, int? ageId = null, int? genderId = null)
{
var classes = databaseContext.Set<Class>();
if (heightId.HasValue)
classes = classes.Where(c => c.HeightId == heightId.Value);
if (ageId.HasValue)
classes = classes.Where(c => c.AgeId == ageId.Value);
if (heightId.HasValue)
classes = classes.Where(c => c.GenderId == genderId.Value);
return classes.Take(limit).ToArray();
}
所以,现在FindByFilter(10, 1, null, 2)
或同等FindByFilter(10, heightId: 1, genderId: 2)
将返回身高1,性别2,但任何年龄TOP 10行。
所以,你有一个类(或多个类)与数量有限的属性,可能比100少。
某处在你的代码,这可能是在用户界面,但它也可以是阅读的网络页面,文件,或者在你的代码从数据库中获取信息,地方你有一些输入,从中可以决定之后, Where
必须执行。
因此,在你的代码的某个地方,你有一个函数,产生了一些输入的返回你在表达:
Expression<Func<MyTable, bool>> CreateExpression(MyInput input) {...}
问题是,我们不知道你是怎么得到的输入。我们所知道的是,仅仅是有一个有限的(小于前面提到的100)可能的输出。如果有输入错误,不是程序应纠正这一成最佳猜测输出,或拒绝产生输出。
无论如何,这漫长的故事是要告诉你,那应该创建表达式的代码是相对有限的。如果你不让它动,而是创建一个非动态功能,即使你有50例大switch语句这是更好的方式可以理解的,可测试,可维护。
例如:假设操作者必须输入姓名和他要过滤的属性的值。他可能会让这种情况下你警告打字错误操作员输入错误
Expression<Func<MyTable, bool>> CreateExpression(string input, int value)
{
// TODO: make the procedure case insensitive
switch (input)
{
case "HeightId":
return myItem => myItem.HeightId == value;
case "AgeId":
return myItem => myItem.AgeId == value;
...
default:
WarnUserIncorrectInput(...)
return null;
}
}
多少情况下,你期待什么呢?即使有20个,这些代码会更容易理解,并检查比如果你会用一些神奇的演绎创造你的表达错误输入。毕竟:这个神奇的解释也应该检查错误输入。
如果在未来的某个属性将被添加或删除,那么这将是相当容易保持这种功能。
复杂的表达式
这可能是你想要的操作者使用一些定义的语言来表达结合起来,是这样的:
"HeightId == 4 AND AgeId == 10 OR ..."
如果您会选择这样那样的投入,你让你的生活非常困难。你几乎就必须建立某种形式的编译器这一点,检查各种错误输入。你必须在操作装置的特性进行检测,当他指的操作,或者比较器。这不容易做到。
如果你真的想表达合并的可能性,考虑使用的用户界面元素,如组合框,用户必须选择一个属性,然后键入正确的值类型。
因为属性的数目是有限的,则可以使用一个程序像上面以产生表达。该组合像下面做:
ExpressionFunc<TSource, bool>> CreateAnd<TSource>(
Expression<Func<TSource, bool>> X,
Expression<Func<TSource, bool>> Y)
{
return (sourceElement) => X(sourceElement) && Y(sourceElement);
}
还是那句话:即使你不想让运营商合并报表,如果使用组合框或类似的,你不能得到不正确的输入,以及组合的数量也相当有限。
结论
虽然可以创建一个字符串输入一个表达式,这将意味着你必须创建一个编译器般的东西,检查错误的输入。这不会是容易理解,测试,维护。
作为其中的语句相当有限的请求数,大概不到100,可以考虑使用的功能有一个大的switch-case