同一字段上有多个 where 子句参数的 LINQ-to-SQL 奇怪之处

发布于 2024-10-08 19:58:10 字数 919 浏览 1 评论 0原文

我的问题要求我根据用户输入动态地将 where 子句添加到 IQueryable 中。我遇到的问题是 Linq-to-SQL 似乎不喜欢在同一字段上有多个 where 子句,它实际上复制了所有参数上最后一项的搜索参数值。我通过 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 子句,如下所示。我的问题是如何解决这个问题?这看起来像是该工具的一个错误,不是吗?

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

My problem requires me to dynamically add where clauses to a IQueryable based on user input. The problem i'm having is that Linq-to-SQL doesn't seem to like having multiple where clauses on the same field, it actually duplicates the search arg value for the last item on all parameters. I verified this behavior through a SQL trace. Here is what I'm seeing.

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%]

My code uses a loop to dynamically add the where clauses as you can see below. My question is how do I work around this? This pretty much seems like a bug with the tool, no?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你不是我要的菜∠ 2024-10-15 19:58:10

结束超过循环变量被认为是有害的!更改

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

Closing over the loop variable considered harmful! Change

foreach(Match searchToken in searchTokens) {
    query = query.Where(
        material => material.OpenText.Contains(searchToken.Value)
    );
}

to

foreach(Match searchToken in searchTokens) {
    Match token = searchToken;
    query = query.Where(
        material => material.OpenText.Contains(token.Value)
    );
}
め可乐爱微笑 2024-10-15 19:58:10

您正在关闭循环变量,即 被认为是有害的。要解决此问题,请执行以下操作:

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,而不是创建查询时它所具有的。当变量的值发生变化时,您的所有查询都会看到新值。

You are closing over the loop variable, which is considered harmful. To fix do this:

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

The reason why your version doesn't work is that the query refers to the variable searchToken, not the value it had when the query was created. When the variable's value changes, all your queries see the new value.

不甘平庸 2024-10-15 19:58:10

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

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

I don't have enough rep to leave comments yet (or this would be a comment and not an answer) but the answers listed here worked for me.

However, I had to turn off compiler optimizations in order for it to work. If you do not turn off compiler optimizations (at least at the method level) then the compiler sees you setting a loop variable to a local variable and throws the local variable away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文