Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/311.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# 需要使用Linq在循环中添加Where子句的帮助吗_C#_Linq_Linq To Entities - Fatal编程技术网

C# 需要使用Linq在循环中添加Where子句的帮助吗

C# 需要使用Linq在循环中添加Where子句的帮助吗,c#,linq,linq-to-entities,C#,Linq,Linq To Entities,下面是一个粗略简化的代码示例,说明了我正在尝试做的事情,但它并没有按预期工作。我正在使用Linq转换实体,以防出现问题 基本上,在第一个循环中,如果我有两个date子句,DateClause的结果是什么都不返回,使用一个date子句效果很好。在TextClause的循环中,它似乎忽略了第一个文本子句之后的每个文本子句 我的期望是这些子句将被and放在一起,这样,如果我做一个文本子句,然后再做另一个,它们应该被添加,我将得到一个更集中的结果,特别是使用Contains方法 对日期的期望是,我希望能

下面是一个粗略简化的代码示例,说明了我正在尝试做的事情,但它并没有按预期工作。我正在使用Linq转换实体,以防出现问题

基本上,在第一个循环中,如果我有两个date子句,DateClause的结果是什么都不返回,使用一个date子句效果很好。在TextClause的循环中,它似乎忽略了第一个文本子句之后的每个文本子句

我的期望是这些子句将被and放在一起,这样,如果我做一个文本子句,然后再做另一个,它们应该被添加,我将得到一个更集中的结果,特别是使用Contains方法

对日期的期望是,我希望能够用它来做一个日期范围,但是如果有两个日期,它总是不返回任何内容,即使我知道在这个范围内有正确日期的记录

我肯定我做错了什么,或者说我很愚蠢,但我看不出来

enum Operators
{
    Contains,
    DoesNotContain,
    GreaterThan,
    LessThan
}

public void DoSomething(List<DateClauses> dateClauses, List<TextClauses> textClauses)
{
    var query = from t in context.Table
                where t.Enabled = true
                select new
                {
                    title = t.title
                    date = t.date
                }


    foreach (DateClause clause in dateClauses)
    {
        switch (clause.Operator)
        {
            case Operator.GreaterThan:
                query = query.Where(l => l.date > clause.Date);
                break;
            case Operator.LessThan
                query = query.Where(l => l.date < clause.Date);
                break;
        }       
    }

    foreach (TextClause clause in textClauses)
    {
        switch (clause.Operator)
        {
            case Operator.Contains:
                query = query.Where(l => l.title.Contains(clause.Text));
                break;
            case Operator.DoesNotContain
                query = query.Where(l => !l.title.Contains(clause.Text));
                break;
        }
    }
}
enum运算符
{
包含,
不涉及,
比,
莱斯坦
}
public void DoSomething(列出日期子句、列出文本子句)
{
var query=来自context.Table中的t
其中t.Enabled=true
选择新的
{
title=t.title
日期=t.date
}
foreach(DateClaires中的DateClaires子句)
{
开关(第条操作员)
{
case Operator.GreaterThan:
query=query.Where(l=>l.date>clause.date);
打破
案例接线员LessThan
query=query.Where(l=>l.datel.title.Contains(子句.Text));
打破
case Operator.DoesNotContain
query=query.Where(l=>!l.title.Contains(子句.Text));
打破
}
}
}
编辑:更新示例代码以显示进程中枚举的使用。当我将枚举的使用外推到一些非常好的解决方案(否则将与bool一起工作)时,Joel的回复中我的评论中显示了一个异常


我想说我喜欢到目前为止我在回复中看到的,并且我已经学会了一些新的Linq技巧,我为这个例子道歉,因为我认为bool vs enum对Linq不会有多大影响。我希望这些改变将有助于找到一个适合我的解决方案。再次感谢您迄今为止的精彩回复。

我以前做过,没有任何问题-也许您应该尝试将.Select移到末尾(在完成where之后)。此外,我还大量使用动态查询内容来增加灵活性——现在,您得到了附加where的“and”语义,我猜您想要的是“and”语义,或者至少其中一些语义。PredicateBuilder让您可以轻松地做到这一点(而且它是免费的!)。

只是一个粗略的猜测,但是将循环更改为以下内容会有不同的结果吗

foreach (DateClause clause in dateClauses)
{
    var capturedClause = clause;
    switch (clause.Operator)
    {
            case Operator.GreaterThan:
                    query = query.Where(l => l.date > capturedClause.Date);
                    break;
            case Operator.LessThan
                    query = query.Where(l => l.date < capturedClause.Date);
                    break;
    }               
}
foreach(日期子句中的日期子句)
{
var capturedClause=条款;
开关(第条操作员)
{
case Operator.GreaterThan:
query=query.Where(l=>l.date>capturedClause.date);
打破
案例接线员LessThan
query=query.Where(l=>l.date
您正在创建捕获循环变量的Where条件,而不是每个迭代的循环变量值。因此,在最后一次迭代之后执行查询时,使用循环最后一次迭代的值,每个Where都是相同的。通过引入一个临时变量,您将为每次迭代捕获该变量


另请参见埃里克·利珀特的。

同样,我本以为这会奏效。我建议设置一个跟踪,看看结果查询是什么样子。当然,因为这显然不是真正的代码,所以其他地方可能有问题。在.Where()的末尾添加.ToList()。@rmoore:nooooooo!在这里添加.ToList()没有帮助,在不需要的地方添加它对性能有害。@Joel Coehoorn我同意这是有害的,但它应该修复它。这是一个简化的代码示例,在实际代码中,我必须使用where子句方法,因为它们需要是动态的,用户可以控制“过滤”的内容在运行时,未更改和未更改的内容也会更改。选择需要在它所在的位置。我尝试了日期选择,但它不起作用。它编译但获取运行时NotSupportedException“无法创建“Closure type”类型的常量值。在此上下文中仅支持基元类型('如Int32、String和Guid')。”这似乎不受Linq to Entity.Odd的支持。这是绝对支持的。在这里,您的错误消息中突出的关键词是
constant
。我在这段代码中看不到任何创建的常量。这是在一个函数中,您将调用它来初始化一个常量吗?我想这个常量将是我在实际代码中的枚举。在我的示例中,子句.Contains将是子句.Operator(它是一个枚举),而不是If语句,我有一个开关。我应该让它成为一个枚举,这就是它是什么,我不认为这会有什么关系,我想保持简单的例子,我想我可能已经把它太简单了。我所做的是将你的(c=>c.Contains)转换为(c=>c.Operator==Operator.Contains),这将得到相同的结果,但是我知道Linq有时不能像你想象的那样工作。哇,这么简单的事情解决了这个问题,允许我使用循环。谢谢你,鲁本。奇怪的是foreach与谓词的区别,感谢您提供的信息和博客文章的链接。
var query = context.Table.Where(t => t.Enabled).Select(t =>  new {
               title = t.title
               date = t.date
      });

query = query.Where(t => textClauses.Where(c => c.Contains).All(c => t.title.Contains(c.Text) );
query = query.Where(t => textClauses.Where(c => c.DoesNotContain).All(c => !t.title.Contains(c.Text) );
query = query.Where(t => dateClauses.Where(c => c.GreaterThan).All(c => t.date > c.Date) );
query = query.Where(t => dateClauses.Where(c => c.LesserThan).All(c => t.date < c.Date) );
foreach (DateClause clause in dateClauses)
{
    var capturedClause = clause;
    switch (clause.Operator)
    {
            case Operator.GreaterThan:
                    query = query.Where(l => l.date > capturedClause.Date);
                    break;
            case Operator.LessThan
                    query = query.Where(l => l.date < capturedClause.Date);
                    break;
    }               
}