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