Мне нужно написать запрос, который будет выполнять поиск по ключевым словам в таблице базы данных. Код в настоящее время выглядит примерно так (хотя и с жестко заданным набором ключевых слов):
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 содержит только ссылку на последнее значение ("Чарли").
Что я должен сделать, чтобы избежать этой проблемы? Я мог бы, вероятно, преобразовать story с запросом в список перед применением каждого нового ключевого слова where, но это кажется неэффективным.
решаемые
Спасибо за все ответы. В итоге у меня возникли две отдельные проблемы, обе из которых были решены:
- Используйте локальную переменную внутри цикла foreach (), чтобы избежать проблемы «Доступ к измененному замыканию».
- Используйте PredicateBuilder в LINQKit для динамической компоновки списка предложений OR для поиска по ключевым словам любого типа.