Нечетность LINQ-to-SQL с несколькими аргументами where в одном поле - PullRequest
2 голосов
/ 21 декабря 2010

Моя проблема требует, чтобы я динамически добавлял предложения where в IQueryable на основе пользовательского ввода.Проблема, с которой я столкнулся, заключается в том, что Linq-to-SQL, похоже, не нравится иметь несколько предложений where в одном поле, а фактически дублирует значение arg поиска для последнего элемента по всем параметрам.Я проверил это поведение через трассировку SQL.Вот что я вижу.

WHERE ([t22].[OpenText] LIKE @p11) AND ([t22].[OpenText] LIKE @p12) 
-- @p11: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%] // Should be 2da57652-dcdf-4cc8-99db-436c15e5ef50
-- @p12: Input NVarChar (Size = 10; Prec = 0; Scale = 0) [%classify%]

Мой код использует цикл для динамического добавления предложений where, как вы можете видеть ниже.Мой вопрос, как мне обойти это?Это похоже на ошибку в инструменте, не так ли?

// add dyanmic where clauses based on user input.
MatchCollection searchTokens = Helper.ExtractTokensWithinBracePairs(filterText);
if (searchTokens.Count > 0)
{
    foreach(Match searchToken in searchTokens)
        query = query.Where((material => material.OpenText.Contains(searchToken.Value)));
}
else
{
    query = query.Where((material => material.OpenText.Contains(filterText)));
}

Ответы [ 3 ]

3 голосов
/ 21 декабря 2010

Закрытие переменной цикла считается вредным! Изменить

foreach(Match searchToken in searchTokens) {
    query = query.Where(
        material => material.OpenText.Contains(searchToken.Value)
    );
}

на

foreach(Match searchToken in searchTokens) {
    Match token = searchToken;
    query = query.Where(
        material => material.OpenText.Contains(token.Value)
    );
}
1 голос
/ 21 декабря 2010

Вы закрываете переменную цикла, которая считается вредной . Чтобы исправить это:

foreach(Match searchToken in searchTokens)
{
    Match searchToken2 = searchToken;
    //    ^^^^^^^^^^^^  copy the value of the reference to a local variable.

    query = query.Where(material => material.OpenText.Contains(searchToken2.Value));
    //                                       use the copy here ^^^^^^^^^^^^  
}

Причина, по которой ваша версия не работает, заключается в том, что запрос относится к переменной searchToken, а не к значению , которое было при создании запроса. Когда значение переменной изменится, все ваши запросы увидят новое значение.

0 голосов
/ 13 апреля 2011

У меня недостаточно представителей, чтобы оставлять комментарии (или это будет комментарий, а не ответ), но ответы, перечисленные здесь, сработали для меня.

Однако мне пришлось отключить оптимизацию компилятора, чтобы он работал. Если вы не отключите оптимизацию компилятора (по крайней мере, на уровне метода), то компилятор увидит, что вы устанавливаете переменную цикла для локальной переменной, и выбрасывает локальную переменную.

...