6

I made this search method on my Entity Framework repo:

public IEnumerable<Person> GetPersonsWithFilter(string filter)
{
    var items = 
        filter.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
    var query = _personRepo.All();  // Return IQueryable<Person>

    foreach (var item in items)
    {
        query = query.Where(i => i.SearchName.Contains(item.ToLower()));
    }

    query.TraceSql(i => Logger.Error(i));
    return query.Take(50);
}

The TraceSql outputs the resulting sql. If my filter is "John Landheer", the sql is correctly generated:

SELECT   [Extent1].[PersonId] AS [PersonId] // Other fields deleted for readability
FROM [dbo].[Person] AS [Extent1]  
WHERE 
(( CAST(CHARINDEX(LOWER(@p__linq__0), [Extent1].[SearchName]) AS int)) > 0) 
AND 
(( CAST(CHARINDEX(LOWER(@p__linq__1), [Extent1].[SearchName]) AS int)) > 0)  

BUT, the parameters are the same: @p_linq_0 = 'landheer' and @p_linq_1 = 'landheer'

Now, if I change the loop to this:

foreach (var item in items)
{
    var tempItem = item;
    query = query.Where(i => i.SearchName.Contains(tempItem.ToLower()));
}

Everything works?!?!

I assume it has something to do with the way EF builds an expression tree, but it looks a bit unexpected. Can anybody shed some light on this?

John

Branislav Abadjimarinov
  • 5,101
  • 3
  • 35
  • 44
John Landheer
  • 3,999
  • 4
  • 29
  • 53
  • It's because of captured variables see http://stackoverflow.com/questions/295593/linq-query-built-in-foreach-loop-always-takes-parameter-value-from-last-iteration – Diego Mar 21 '11 at 16:35

1 Answers1

0

Thanks Equiso, I didn't find the question you refered to. So this is an exact duplicate of Linq query built in foreach loop always takes parameter value from last iteration.

Community
  • 1
  • 1
John Landheer
  • 3,999
  • 4
  • 29
  • 53