Фильтрация IQueryable <T>возвращает неверный результат - PullRequest
2 голосов
/ 30 ноября 2011

Я только что столкнулся с довольно удивительной проблемой.

Случай прост: вернуть все объекты, которые в данный момент активны, что означает: отфильтровать все результаты, возвращенные методом GetAll(), в соответствии с их логическим свойством Active

public IQueryable<T> GetAllActive()
{
      return implementation.GetAll().Where(a => ((IDeactivable)a).Active);  
}

где GetAll() метод объекта реализации определяется как:

public IQueryable<T> GetAll();

Проблема в том, что GetAllActive() возвращает все записи, независимо от значения их свойства Active,точно так же, как нет предложения Where.

В чем может быть причина этого?

Примечание: Код упрощен, тип T проверен для реализацииIDeactivable интерфейс.Также во время выполнения не генерируется никаких исключений.

Редактировать: IQueryable, возвращаемый объектом реализации, поступает из NHibernate

Edit2: Я использовал следующий кодчтобы проверить фактические значения для сущностей (кроме использования VS Debugger):

foreach (var a in active) {              //active -> filtered IQueryable before return
        _logger.Warn(a.Id);
        _logger.Warn(((IDeactivable)a).Active);
}

результат был:

11/30/2011 18:10:00 WARN xxx.Repository`1.GetAllActive: 70db43fa-2361-4c1f-a8e5-9fab012b5a2b
11/30/2011 18:10:01 WARN xxx.Repository`1.GetAllActive: False
11/30/2011 18:10:02 WARN xxx.Repository`1.GetAllActive: 5493c9bb-ec6e-4690-b5d6-9fab012b5b16
11/30/2011 18:10:02 WARN xxx.Repository`1.GetAllActive: True

Ответы [ 2 ]

5 голосов
/ 30 ноября 2011

Когда вы возвращаете IQueryable<T>, вы на самом деле не возвращаете набор результатов.То, что вы возвращаете, это объект, к которому можно обратиться.

Выполнение .Where() метода отложено до тех пор, пока вы (или кто-либо, вызывающий ваш метод) фактически не заставитеисполнение цепочки Linq.Это то, что позволяет нижестоящим клиентам применять свои дополнительные методы Linq к результату и все еще получать ленивую оценку для всей цепочки Linq.

Так что, когда вы говорите, что IQueryable<T> возвращает все записи, вы, вероятно, просматриваете результат в отладчике и показывает исходный набор данных без фильтрации (поскольку .Where() еще не выполнен).

Причина того, что приведение к IEnumerable работает, заключается в том, что запускает выполнение цепочки команд Linq, , и в результате получается достоверный список, а не объект, к которому можно обратиться. Вызов ToList() или ToArray() также вызовет выполнение.

Короче говоря, единственный способ убедиться, что вы видите правильный результат из ваших методов Linq во время тестирования* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *} * *}}}}}}}} * * * * * * * ЕГО * 10 30 *.Он содержит пример, показывающий, как на самом деле вы можете столкнуться с проблемами при возврате IQueryable из блока using, потому что объект IQueryable удаляется до выполнения запроса.

0 голосов
/ 01 декабря 2011

Я испробовал несколько разных подходов и наконец нашел часть своего кода, которая еще не была протестирована.Оказалось, что LINQ Queries to NHibernate вызывал некоторые проблемы при использовании условия Where, которых я раньше не замечал.

В конце концов я понял, что использую неправильную версию LINQ для NHibernate QueryProvider (неодин включен в NH 3.0), и это известная проблема.Теперь, когда я избавился от этого, все работает отлично.СПАСИБО ЗА ПОМОЩЬ, ПАРНИ!Вы указали мне правильное направление.

Упомянутая проблема описана в следующей теме: Проблема с запросом linq

...