我的问题要求我根据用户输入动态地向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)));
}
答案 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)
我还没有足够的代表留下评论(或者这将是评论,而不是答案),但这里列出的答案对我有用。
但是,我必须关闭编译器优化才能使其正常工作。如果不关闭编译器优化(至少在方法级别),编译器会看到您将循环变量设置为局部变量并抛出局部变量。