LINQ“Where”语句不起作用

时间:2011-11-02 12:13:22

标签: c# .net linq entity-framework linq-to-entities

我有点困惑为什么这段代码在列表中产生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行为错误。

3 个答案:

答案 0 :(得分:1)

修改:在查询结尾处看到您有ToList,因此以下内容不适用。


阅读closures and 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);

答案 1 :(得分:1)

您在评论中提到的

IDbSet是实体框架的一部分,因此您的2段代码不相同。 LINQ是一个表达式树,它由EF转换为SQL,而第一位代码从数据库中恢复整个表并在内存中执行循环。对数据库进行概要分析以找出数据库中正在执行的SQL,这可以让您了解为什么linq不能执行您想要的操作。

答案 2 :(得分:1)

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

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