LINQ“哪里”声明不起作用

发布于 2024-12-13 01:54:03 字数 629 浏览 0 评论 0原文

我有点困惑为什么这段代码会在列表中生成 2 条记录(行为适当):

var historiesToRemove = new List<WorkHistory>();
                foreach (var history in this.WorkHistories)
                {
                    if (history.Tool.Equals(item))
                    {
                        historiesToRemove.Add(history);
                    }
                }

虽然这段代码会生成一个空列表:

var historiesToRemove = this.WorkHistories.Where(history => history.Tool.Equals(item)).ToList();

有什么想法为什么会发生这种情况吗?

原因:

我没有正确实现 IDbSet 的 IQueryable 属性。这使得我的 LINQ 行为错误。

I'm a bit confused why this piece of code produces 2 records in a list (acts appropriately):

var historiesToRemove = new List<WorkHistory>();
                foreach (var history in this.WorkHistories)
                {
                    if (history.Tool.Equals(item))
                    {
                        historiesToRemove.Add(history);
                    }
                }

While this piece of code produces an empty list:

var historiesToRemove = this.WorkHistories.Where(history => history.Tool.Equals(item)).ToList();

Any ideas why could this happen?

REASON:

I didn't properly implement IDbSet's IQueryable properties. This made my LINQ act wrong.

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

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

发布评论

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

评论(3

提笔书几行 2024-12-20 01:54:03

您在评论中提到的 IDbSet 是实体框架的一部分,因此您的两段代码并不等效。 LINQ 是一个表达式树,由 EF 转换为 SQL,而代码的第一位从数据库中检索整个表并在内存中执行循环。分析数据库以找出数据库中正在执行的 SQL,这应该会让您了解为什么 linq 不执行您想要的操作。

IDbSet that you mention in a comment is part of the entity framework so your 2 pieces of code are not equivalent. The LINQ is an expression tree that gets converted to SQL by EF whereas the first bit of code retreieves the entire table from the database and executes the loop in memory. Profile the database to find out what SQL is executing in the database and this should give you an idea why the linq does not do what you want.

ㄟ。诗瑗 2024-12-20 01:54:03

编辑:刚刚看到查询末尾有ToList,因此以下内容不适用。


阅读闭包和 LINQ。在运行查询之前,“item”可能正在更改。

问题代码示例:

var filter = "Compare";

var query = from m in typeof(String).GetMethods()
            where m.Name.Contains(filter)
            select new { m.Name, ParameterCount = m.GetParameters().Length };

filter = "IndexOf";

foreach (var item in query)
    Console.WriteLine(item);

Edit: Just saw you have ToList on the end of the query, so the below does not apply.


Read up on closures and LINQ. Probably 'item' is changing before you run the query.

Example problem code:

var filter = "Compare";

var query = from m in typeof(String).GetMethods()
            where m.Name.Contains(filter)
            select new { m.Name, ParameterCount = m.GetParameters().Length };

filter = "IndexOf";

foreach (var item in query)
    Console.WriteLine(item);
九厘米的零° 2024-12-20 01:54:03

这只是一个猜测,但我想说您可能提供了与 EF 中 LINQ 翻译所使用的不同的相等定义。在 EF 中,我相信它使用属性相等,而您可能只检查 ID 是否相同。我建议您对要在 LINQ 语句中检查的相等性定义进行显式编码。您的相等定义在第一种情况下起作用的原因是,枚举 IDbSet 将其带入内存,从而调用您的 Equals 版本,而不是 Equals 的 LINQ 到 EF 转换。

 var historiesToRemove = this.WorkHistories.Where( h => h.Tool.ID == tool.ID )
                                           .ToList();

This is just a guess, but I would say that you've probably provided a definition of equality that is different than that used by the LINQ translation in EF. In EF I believe that it uses property equality, whereas you might only be checking that the IDs are the same. I suggest that you explicitly encode the definition of equality that you want to check in your LINQ statement. The reason that your equality definition works in the first case is that enumerating the IDbSet brings it into memory and thus invokes your version of Equals rather than the LINQ-to-EF translation of Equals.

 var historiesToRemove = this.WorkHistories.Where( h => h.Tool.ID == tool.ID )
                                           .ToList();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文