1

バグのトラブルシューティング中に、私はこれに遭遇しました。実行が延期されたことが原因のようで、クエリは変数キーワードの最後の値を使用しています。これを解決するために推奨されるパターンは何ですか。

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

このようなクエリの結果(両方のパラメータの値が「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%'

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

1 に答える 1

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

そしてそれは動作するはずです。詳細については、 EricLippertのブログ投稿を参照してください。C#5では動作が変更されているため、その時点で心配する必要はありません。

ただし、LINQにこれを実行させることもできます。

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

私はそれがAny(「OR」を効果的に)機能させると確信していますが、それがで機能するかどうかはわかりませんAll。試してみてください...

于 2012-04-19T19:23:50.343 に答える