データベーステーブルでキーワード検索を実行するクエリを作成する必要があります。現在、コードは次のようになっています(ただし、ハードコードされたキーワードのセットがあります)。
var keywords = new [] { "alpha", "bravo", "charlie" };
IQueryable<Story> stories = DataContext.Stories;
foreach( var keyword in keywords )
{
stories = from story in stories where story.Name.Contains ( keyword ) );
}
return stories;
ReSharperは、foreach内のキーワードに対して「変更されたクロージャへのアクセス」警告をスローします。エラーを理解し、生成されたSQLを確認して問題を確認します。
SELECT [t0].[Id], [t0].[Name]
FROM [dbo].[Story] AS [t0]
WHERE (([t0].[Name] LIKE @p0))
AND (([t0].[Name] LIKE @p1))
AND (([t0].[Name] LIKE @p2))
-- @p0: Input NVarChar (Size = 9; Prec = 0; Scale = 0) [%charlie%]
-- @p1: Input NVarChar (Size = 9; Prec = 0; Scale = 0) [%charlie%]
-- @p2: Input NVarChar (Size = 9; Prec = 0; Scale = 0) [%charlie%]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.30729.1
キーワードイテレータはループ中に変更されるため、私のSQLには最後の値( "charlie")への参照のみが含まれています。
この問題を回避するにはどうすればよいですか?新しいキーワードwhere句を適用する前に、クエリ可能なストーリーをリストに変換することもできますが、それは非効率的です。
解決済み
すべての答えをありがとう。最終的に、2つの別々の問題が発生しましたが、どちらも解決されました。
- 「変更されたクロージャへのアクセス」の問題を回避するには、foreach()ループ内でローカル変数を使用します。
- LINQKitのPredicateBuilderを使用して、OR句のリストを動的にアセンブルし、「任意の」スタイルのキーワード検索を可能にします。