Linq to sql 同一字段上有多个where子句参数的LINQ到SQL奇点

Linq to sql 同一字段上有多个where子句参数的LINQ到SQL奇点,linq-to-sql,dynamic,where-clause,Linq To Sql,Dynamic,Where Clause,我的问题要求我根据用户输入动态地将where子句添加到IQueryable。我遇到的问题是,Linq to SQL似乎不喜欢在同一字段上有多个where子句,它实际上复制了所有参数上最后一项的搜索arg值。我通过SQL跟踪验证了这种行为。这是我看到的 WHERE ([t22].[OpenText] LIKE @p11) AND ([t22].[OpenText] LIKE @p12) -- @p11: Input NVarChar (Size = 10; Prec = 0; Scale = 0

我的问题要求我根据用户输入动态地将where子句添加到IQueryable。我遇到的问题是,Linq to SQL似乎不喜欢在同一字段上有多个where子句,它实际上复制了所有参数上最后一项的搜索arg值。我通过SQL跟踪验证了这种行为。这是我看到的

WHERE ([t22].[OpenText] LIKE @p11) AND ([t22].[OpenText] LIKE @p12) 
-- @p11: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%] // Should be 2da57652-dcdf-4cc8-99db-436c15e5ef50
-- @p12: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%]
我的代码使用循环来动态添加where子句,如下所示。我的问题是如何解决这个问题?这看起来像是工具的一个bug,不是吗

// add dyanmic where clauses based on user input.
MatchCollection searchTokens = Helper.ExtractTokensWithinBracePairs(filterText);
if (searchTokens.Count > 0)
{
    foreach(Match searchToken in searchTokens)
        query = query.Where((material => material.OpenText.Contains(searchToken.Value)));
}
else
{
    query = query.Where((material => material.OpenText.Contains(filterText)));
}

您正在关闭循环变量,即。要解决此问题,请执行以下操作:

foreach(Match searchToken in searchTokens)
{
    Match searchToken2 = searchToken;
    //    ^^^^^^^^^^^^  copy the value of the reference to a local variable.

    query = query.Where(material => material.OpenText.Contains(searchToken2.Value));
    //                                       use the copy here ^^^^^^^^^^^^  
}
版本不起作用的原因是查询引用了变量searchToken,而不是创建查询时的值。当变量的值更改时,所有查询都会看到新值。

更改


我还没有足够的代表留下评论(或者这只是一个评论而不是一个答案),但是这里列出的答案对我很有用


但是,我必须关闭编译器优化才能让它工作。如果不关闭编译器优化(至少在方法级别),编译器会看到您将循环变量设置为局部变量,并将局部变量丢弃

因为它需要最后一个?@khachik:当lambda表达式中有一个局部变量时,会发生什么情况?该变量会被捕获到编译器生成的类中。在循环的每次迭代中,您都在修改这个变量,但是所有lambda表达式都会看到它,因为它们都会看到这个编译器生成的类的相同实例。在循环中创建一个新的局部可以消除这个问题,因为现在我们正在将这个局部捕获到编译器生成的类中,并且在每个循环迭代中实例化这个类的一个新实例。
foreach(Match searchToken in searchTokens) {
    query = query.Where(
        material => material.OpenText.Contains(searchToken.Value)
    );
}
foreach(Match searchToken in searchTokens) {
    Match token = searchToken;
    query = query.Where(
        material => material.OpenText.Contains(token.Value)
    );
}