While troubleshooting a bug I ran into this. It seems to be due to deferred execution and the query is using the last value of variable keyword. What is the recommended pattern to solve this.
var query = from c in dbContext.Cars
select c;
var keywords = new string[] { "Clean", "Car" };
foreach (var keyword in keywords)
{
query = query.Where(c => c.Name.Contains(keyword));
}
var cars = query.ToList();
Results in query like this (note the value of both parameters is “Car”)
exec sp_executesql N'SELECT
[Extent1].[CarID] AS [MID],
[Extent1].[Name] AS [Name],
FROM [dbo].[Cars] AS [Extent1]
WHERE ([Extent1].[Name] LIKE @p__linq__0 ESCAPE N''~'') AND ([Extent1].[Name] LIKE @p__linq__1 ESCAPE N''~'')
',N'@p__linq__0 nvarchar(4000),@p__linq__1 nvarchar(4000)',@p__linq__0=N'%Car%',@p__linq__1=N'%Car%'
Debugging in LINQPad also shows same query
DECLARE p__linq__0 NVarChar(1) = '%Car%'
DECLARE p__linq__1 NVarChar(1) = '%Car%'
SELECT
[Extent1].[CarID] AS [MID],
[Extent1].[Name] AS [Name],
FROM [dbo].[Cars] AS [Extent1]
WHERE ([Extent1].[Name] LIKE @p__linq__0 ESCAPE N'~') AND ([Extent1].[Name] LIKE @p__linq__1 ESCAPE N'~')
It’s due to the way variables are captured in anonymous functions. Change this:
to this:
and it should work. See Eric Lippert’s blog post for more details. The behaviour is changing for C# 5, so you won’t need to worry at that point.
Note, however, that you could also try to let LINQ do this for you:
I’m pretty sure that would work for
Any(an “OR” effectively) but I don’t know for sure whether it will work withAll. Work a try…