简体   繁体   中英

strange behavior in linq to sql

I'm trying to find all element that contains all words in a phrase after geting them from database:

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
}

everything is alright till this:

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
}

without doing anything at the second loop the element count changes furthermore this should return only element with all the words but it return element with just the last one and the third loop is useless changes nothing

I'm sorry for the long Q but I'm new to linq

I think this may be the dreaded "modified closure" error. Create a temporary copy of the word loop variable, and use it instead in your queries.

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
}

You should avoid using loop variables in LINQ expressions, unless you "materialize" them right away (ie call ToList() , ToArray , First() , SingleOrDefault , etc.) When you need to use the value of your loop variable, make a temporary copy. The reason is that LINQ defers execution of your query, so when by the time the query gets executed the value of the loop variable has changed, your results will change unexpectedly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM