Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有条件AND、OR和NOT筛选器的Linq谓词生成器_C#_Linq_Linq To Sql_Predicatebuilder - Fatal编程技术网

C# 具有条件AND、OR和NOT筛选器的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); } 内部静态表达式描述(字符串

我们有一个使用LINQtoSQL的项目,为此我需要重写几个搜索页面,以允许客户机选择是否要执行and或or搜索

我考虑使用重新执行LINQ查询,我想这已经很好地工作了。我实际上有一个包含谓词的类,例如:

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(谓词);
}
}
返回查询;
}
虽然我对此相当满意,但我有两个顾虑:

  • 评估SearchType属性的if/else块感觉可能是潜在的代码气味
  • 客户现在坚持要能够执行“而不是“/”或“不”搜索
  • 为了解决第2点,我想我可以简单地重写我的表达式,例如:

    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;
            }