我正在尝试从数据库中找到包含短语中所有单词的所有元素:
string text = "ab cd 23";//the element prop2 must have all 3 word regardless their order
var q = from c in db.myTable
where c.Prop1 == "value"
select c;
string[] strings = text.Split(' ');
foreach(string word in strings)
{
int cnt = q.Count();//first time cnt = 1500 which is correct
q = q.Where(c => c.Prop2.Contains(word));// Prop2 is a string
cnt = q.Count();//first time cnt = 460
}
一切顺利,直到这个:
foreach(string word in strings)// second time
{
int cnt = q.Count();//second time cnt = 14 ??
q = q.Where(c => c.Prop2.Contains(word));
cnt = q.Count();//first time cnt = 2
}
在第二个循环中没有做任何事情,元素计数会改变 此外,这应该只返回包含所有单词的元素,但它返回的元素只包含最后一个单词 而第三个循环是无用的改变
我很抱歉长Q但我是linq的新手
答案 0 :(得分:3)
我认为这可能是可怕的“修改后的闭包”错误。创建word
循环变量的临时副本,并在查询中使用它。
foreach(string word in strings) {
var tmp = word;
int cnt = q.Count();
q = q.Where(c => c.Prop2.Contains(tmp));
cnt = q.Count();//first time cnt = 460
}
你应该避免在LINQ表达式中使用循环变量,除非你立即“实现”它们(即调用ToList()
,ToArray
,First()
,SingleOrDefault
等。 )当您需要使用循环变量的值时,请进行临时复制。原因是LINQ延迟了查询的执行,所以当查询执行时,循环变量的值已经改变,结果会意外地改变。