Действительно ли мне нужно использовать AsQueryable() для коллекции?

Пример кода:

List<Student> Students = new List<Student>()   
{   
    new Student(101, "Hugo", "Garcia", new List<int>() { 91, 88, 76, 93 }),  
    new Student(102, "Rick", "Adams", new List<int>() { 70, 73, 66, 90 }),  
    new Student(103, "Michael", "Tucker", new List<int>() { 73, 80, 75, 88 }),  
    new Student(104, "Fadi", "Fakhouri", new List<int>() { 82, 75, 66, 84 }),  
    new Student(105, "Peter", "Barrows", new List<int>() { 67, 78, 70, 82 })  
};

var query = from student in Students
            where student.Marks.AsQueryable().All(m => m > 70)
            select student;

foreach (Student student in query)
{
    Console.WriteLine("{0} {1}<br />", student.FirstName, student.LastName);
}

Но если я изменил запрос на

var query = from student in Students
            where student.Marks.All(m => m > 70)
            select student;

Это также работает и дает тот же результат, так что разница?

Ответ 1

IQueryable требуется/рекомендуется для объектов, поступающих из удаленного источника (например, из базы данных).

Для коллекций в памяти это бесполезно.

AsQueryable используется при построении дерева выражений.

Я могу подумать о сценарии, где он лучше всего подходит. В вашем примере предположим, что вам требуется некоторая информация из базы данных на основе идентификатора студента.

Теперь ученик находится в коллекции памяти. Необходимо выполнить запрос базы данных на основе идентификатора студента.

  var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i));

Любая дальнейшая операция над studentList будет вызываться из интерфейса IQueryAble (выражение запроса) и будет извлекать только те записи из источника данных, которые должны быть возвращены в качестве окончательного результата запроса (при условии, что источник данных, возвращаемое значение remoteDBProvider.GetInfo в этом примере поддерживает QueryProvider).

Ответ 2

Он должен делать так, как создается дерево выражений. Посмотрите на это:

AsQueryable - это метод, который позволяет преобразовать запрос в экземпляр IQueryable. Когда вы используете оператор AsQueryable на существующий запрос и применять дальнейшие преобразования, такие как применение фильтровать или указывать порядок сортировки, эти лямбда-выражения преобразованный в деревья выражений. В зависимости от поставщика вы использование деревьев выражений будет преобразовано в конкретную область синтаксис и выполнение. В случае провайдера Linq to SQL дерево выражений будет преобразовано в SQL и выполнено на SQL-сервере. Однако, если вы используете оператор AsQueryable для запроса, который не реализует IQueryable и реализует только IEnumerable, чем любой преобразования, которые вы применяете по запросу, автоматически упадут вернуться к спецификации IEnumerable. Это означает, что запроса с AsQueryable вы получаете преимущества как Linq to SQL, так и Linq для реализации объекта. Если ваш существующий запрос выполняется IQueryable, запрос преобразуется в SQL поставщиком Linq to SQL, в противном случае запрос выполняется в памяти в виде IL-кода.

Ссылка здесь

Ответ 3

В случае вашего List<Student> это не имеет никакого значения, так как возвращенный IQueryable<T> будет использовать те же методы для запроса, как если бы вы не использовали AsQueryable().

Некоторые методы ожидают параметр IQueryable<T>. Я думаю, что метод расширения AsQueryable() в основном полезен для этих сценариев, когда вам нужно передать IQueryable<T>, но только IEnumerable<T>.

MSDN говорит о AsQueryable:

Если тип источника реализует IQueryable<T>, AsQueryable<TElement>(IEnumerable<TElement>) возвращает его напрямую. В противном случае он возвращает IQueryable<T>, который выполняет запросы посредством вызывая эквивалентные методы оператора запроса в Enumerable вместо те в Queryable.

Итак, это означает, что в вашем случае (List<T> не реализует IQueryable<T>), вам действительно не нужно AsQueryable.