2012-04-19 3 views
1

バグのトラブルシューティング中にこの問題が発生しました。これは遅延実行によるもので、クエリはvariableキーワードの最後の値を使用しています。これを解決するための推奨パターンは何ですか?このようなクエリでforeach/forのwhere句を組み込んだ遅延クエリ

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(); 

結果(両方のパラメータの値が「車」であることに注意)

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%' 

LINQPadでのデバッグも同じクエリ

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'~') 

答えて

5

を示しそれは方法が原因です変数は匿名関数で取り込まれます。これに

foreach (var keyword in keywords) 
{ 
    query = query.Where(c => c.Name.Contains(keyword)); 
} 

foreach (var keyword in keywords) 
{ 
    var copy = keyword; 
    query = query.Where(c => c.Name.Contains(copy)); 
} 

、それが動作するはずこれを変更します。詳細はEric Lippert's blog postを参照してください。 C#5の動作が変化しているので、その時点で心配する必要はありません。私はそれがAny(「OR」効果)のために働くだろうかなり確信している

var query = dbContext.Cars.Where(c => keywords.All(key => c.Name.Contains(key)); 

を私はしないでください。

ただし、あなたはまた、LINQはあなたのためにこれをやらせるために試みることができることそれがAllと動作するかどうかを確かめてください。試してみてください...

+0

ありがとうございました@ジョン、それは正常に動作します。エリックのブログリンクもありがとうございました。これは、かなり大きなコードで実際のクエリ構築の非常に短いバージョンですので、Any/Allを使用できるかどうかを確認する必要があります。あまりにもありがとう。 –

+0

他の結合や条件が存在する実際のクエリで使用されたとき、孤立したクエリ(私が投稿したもの)内のすべてが動作する間、EF生成クエリは厄介になり、永遠に実行されます。それは変化が始まり大きなものになる理由かもしれません。内側に新しいクロージャ変数を作成してforeachに固執する。 –