Действительно ли мне нужно использовать 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
.