фильтровать IQueryable в цикле с несколькими операторами Where

#c# #linq

#c# #linq

Вопрос:

у меня есть этот код

 private static IQueryable<Persoon> Filter(IQueryable<Persoon> qF, IDictionary<string, string> filter)
{
    IQueryable<Persoon> temp;
    temp = qF;
    foreach (var key in filter)
    {
        if (key.Key == "naam")
        {
            temp = temp.Where(f => f.Naam == key.Value);
        }
        else if (key.Key == "leeftijd")
        {
            temp = temp.Where(af => af.Leeftijd != null amp;amp; af.Leeftijd.AantalJaarOud.ToString() == key.Value);
        }
    }
    return temp;

}
  

что он делает (это упрощенная версия, созданная для тестирования поведения), так это то, что вы предоставляете этой функции IQueryable Persoon (из базы данных) и список фильтров.

Таким образом, если вы задаете фильтр naam,john и leefttijd,30, вы получаете все объекты Persoon с именем John и возрастом 30.

Когда я вхожу в цикл первым, сразу после того, как я выполняю первый where (последний запрос where) в } после него, я вижу, что у tmp есть 3 объекта. Затем код запускается во второй раз в цикле, вводит первый If (где filter eq naam) и прямо там, когда я смотрю на tmp, у него есть только 0 объектов.

первое представление о том, что это не работает, заключалось в том, что функция не возвращает результатов (должно быть 2: 30 и 2 Джона из них). Итак, я пришел к выводу, что множественный .В чем была проблема.

Но теперь я вижу, что temp пуст еще до того, как я выполню второе where.

Что я делаю не так?

Ответ №1:

Лямбда-выражения LINQ используют позднюю привязку параметров, поэтому, когда xpression окончательно обрабатывается, переменная «key» больше не указывает на правильные значения.

Попробуйте изменить свой код, чтобы сохранить ключ в локальной переменной и использовать его вместо:

 private static IQueryable<Persoon> Filter(IQueryable<Persoon> qF, IDictionary<string, string> filter)
{
    IQueryable<Persoon> temp;
    temp = qF;
    foreach (var key in filter)
    {
        var currentKeyValue = key.Value;
        if (key.Key == "naam")
        {
            temp = temp.Where(f => f.Naam == currentKeyValue);
        }
        else if (key.Key == "leeftijd")
        {
            temp = temp.Where(af => af.Leeftijd != null amp;amp; af.Leeftijd.AantalJaarOud == Int32.Parse(currentKeyValue));
        }
    }
    return temp;

}
  

Еще одна вещь, которую, я думаю, вам следует изменить, — это преобразование поля age в строку, а не в противоположном направлении. поэтому база данных сравнивает числа, а не строки.

Комментарии:

1. вы имеете в виду: когда я выполняю итерацию 20 раз, все WHERE указывают на один и тот же (последний) ключ, а 19 других игнорируются?

2. именно так. Я тоже продолжаю забывать об этом и продолжаю сталкиваться с ошибками, подобными этому.

3. У меня была похожая проблема, это была именно она. Спасибо!