LINQ-to-SQL奇怪,在同一个字段上有多个where子句参数

时间:2010-12-21 20:10:21

标签: linq-to-sql dynamic where-clause

我的问题要求我根据用户输入动态地向IQueryable添加where子句。我遇到的问题是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)));
}

3 个答案:

答案 0 :(得分:3)

Closing over the loop variable considered harmful!更改

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

答案 1 :(得分:1)

您正在关闭循环变量,即considered harmful。要解决这个问题:

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,而不是创建查询时的。当变量的值发生变化时, all 您的查询将看到新值。

答案 2 :(得分:0)

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

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