我想创建一个单独的查询,根据元组“调整”它的where子句。元组中的第一项包含一个枚举值,指示要过滤的字段。第二个元组项是过滤器值。
请注意,下面的查询不起作用:
var query = from p in db.Categories
where ( QueryBy.Item1 == CategoryFields.Name && p.Name == (string)(QueryBy.Item2) ) ||
( QueryBy.Item1 == CategoryFields.Id && p.Id == (long)(QueryBy.Item2) ) ||
( QueryBy.Item1 == CategoryFields.Description && p.Description == (string)(QueryBy.Item2) ) ||
( QueryBy.Item1 == CategoryFields.SortOrder && p.SortOrder == (int)(QueryBy.Item2) )
select...
if (query.Count() == 1) // ERRORS HERE CONVERSION OF INT
仅使用where子句更改的类似查询将起作用:
var query = from p in db.Categories
where ( QueryBy.Item1 == CategoryFields.Name && p.Name == (string)(QueryBy.Item2) )
select...
if (query.Count() == 1) // Works HERE
知道可能出现什么问题吗?可能是LINQ where子句执行短路评估,因此item2的转换失败了吗?有没有更好的方法来实现调整where子句的总体目标?
提前感谢您的帮助!
答案 0 :(得分:3)
LINQ to SQL不够智能,无法优化您的查询并根据QueryBy.Item1
的值动态生成查询。它只会生成一个SQL查询,让SQL服务器自行决定。
当您知道这一点时,错误是有道理的,因为单个值不可能同时转换为int
,long
和string
。
在您的情况下,您最好动态生成正确的where
子句。您可以使用PredicateBuilder:
IQueryable<Category> query = db.Categories;
var whereClause = PredicateBuilder.False<Category>();
switch (QueryBy.Item1)
{
case CategoryFields.Name:
long id = (string)QueryBy.Item2;
whereClause = whereClause.Or(p => p.Name == name);
break;
case CategoryFields.Id:
string name = (string)QueryBy.Item2;
whereClause = whereClause.Or(p => p.Id == id);
break;
case CategoryFields.Description:
string des = (string)QueryBy.Item2;
whereClause =
whereClause.Or(p => p.Description == des);
break;
case CategoryFields.Id:
string sort = (int)QueryBy.Item2;
whereClause =
whereClause.Or(p => p.SortOrder == sort);
break;
}
query = query.Where(whereClause);