C# 具有条件AND、OR和NOT筛选器的Linq谓词生成器
我们有一个使用LINQtoSQL的项目,为此我需要重写几个搜索页面,以允许客户机选择是否要执行and或or搜索 我考虑使用重新执行LINQ查询,我想这已经很好地工作了。我实际上有一个包含谓词的类,例如:C# 具有条件AND、OR和NOT筛选器的Linq谓词生成器,c#,linq,linq-to-sql,predicatebuilder,C#,Linq,Linq To Sql,Predicatebuilder,我们有一个使用LINQtoSQL的项目,为此我需要重写几个搜索页面,以允许客户机选择是否要执行and或or搜索 我考虑使用重新执行LINQ查询,我想这已经很好地工作了。我实际上有一个包含谓词的类,例如: internal static Expression<Func<Job, bool>> Description(string term) { return p => p.Description.Contains(term); } 内部静态表达式描述(字符串
internal static Expression<Func<Job, bool>> Description(string term)
{
return p => p.Description.Contains(term);
}
内部静态表达式描述(字符串术语)
{
返回p=>p.Description.Contains(术语);
}
为了执行搜索,我正在这样做(为了简洁起见,省略了一些代码):
公共表达式ToLinqExpression()
{
var谓词=新列表();
//在这里建立谓词
if(SearchType==SearchType.And)
{
query=PredicateBuilder.True();
}
其他的
{
query=PredicateBuilder.False();
}
foreach(谓词中的var谓词)
{
if(SearchType==SearchType.And)
{
query=query.And(谓词);
}
其他的
{
query=query.Or(谓词);
}
}
返回查询;
}
虽然我对此相当满意,但我有两个顾虑:
internal static Expression<Func<Job, bool>> Description(string term, bool invert)
{
if (invert)
{
return p => !p.Description.Contains(term);
}
else
{
return p => p.Description.Contains(term);
}
}
内部静态表达式描述(字符串术语,布尔反转)
{
如果(反转)
{
返回p=>!p.Description.Contains(术语);
}
其他的
{
返回p=>p.Description.Contains(术语);
}
}
然而,这感觉有点混乱,这通常意味着有更好的解决方案。有人能推荐如何改进这一点吗?我知道动态LINQ,但我真的不想失去LINQ强大的键入功能。如果您希望减少行数,可以用三元运算符替换If/else:
query = SearchType == SearchType.And ? PredicateBuilder.True<Job>() : PredicateBuilder.False<Job>();
foreach (var predicate in predicates)
{
query = SearchType == SearchType.And ? query.And(predicate) : query.Or(predicate);
}
NegateExp方法类似于:
internal static Expression<Func<Job, bool>> Description(string term, bool invert)
{
return NegateExp<Func<Job, bool>>(p => p.Description.Contains(term), invert);
}
public static Expression<TDelegate> NegateExp<TDelegate>(Expression<TDelegate> expression, bool inverse)
{
if (inverse)
{
return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters);
}
return expression;
}
public静态表达式NegateExp(表达式表达式,bool逆)
{
if(逆)
{
返回Expression.Lambda(Expression.Not(Expression.Body)、Expression.Parameters);
}
返回表达式;
}
您可以查看这个问题以获得更多示例我已经分析了生成的SQL,看起来一切正常。关于使用三元运算符的合理评论,尽管我更关心更新的谓词中的重复。这里应该使用Expression.Not with delegate。在上面添加了一个小例子。这是一个有趣的例子,明天将尝试一下。我还想到,我可以简单地用invert参数对表达式进行异或运算——它可以工作,但它会生成一些效率非常低的SQL。工作非常完美,生成干净的SQL。谢谢
public static Expression<TDelegate> NegateExp<TDelegate>(Expression<TDelegate> expression, bool inverse)
{
if (inverse)
{
return Expression.Lambda<TDelegate>(Expression.Not(expression.Body), expression.Parameters);
}
return expression;
}