Мне действительно нужно использовать 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;
Это также работает и дает тот же результат, так в чем же разница?
3 ответа
IQueryable требуется / рекомендуется для объектов, поступающих из удаленного источника (например, из базы данных).
Ибо в коллекциях памяти это бесполезно.
AsQueryable используется, когда должно быть построено дерево выражений.
Я могу думать о сценарии, где это лучше всего подходит. В вашем примере, допустим, вам требуется некоторая информация из базы данных на основе идентификатора студента.
Сейчас студент находится в коллекции памяти. Вам необходимо запустить запрос к базе данных на основе идентификатора студента.
var studentList = Students.Select(s => s.Id).AsQueryAble().Select(i => remoteDBProvider.GetInfo(i));
Любая дальнейшая операция с studentList будет вызываться из интерфейса IQueryAble (выражение запроса) и будет извлекать только те записи из источника данных, которые должны быть возвращены в качестве окончательного результата запроса (при условии, что источник данных возвращает значение remoteDBProvider.GetInfo
в примере, поддерживает QueryProvider).
В случае вашего 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
,
Он должен делать, как строится дерево выражений. Посмотри на это:
AsQueryable - это метод, позволяющий преобразовать запрос в экземпляр IQueryable. Когда вы используете оператор AsQueryable в существующем запросе и применяете дополнительные преобразования, такие как применение фильтра или указание порядка сортировки, эти лямбда-операторы преобразуются в деревья выражений. В зависимости от того, какой провайдер вы используете, деревья выражений будут преобразованы в специфический для домена синтаксис и затем выполнены. В случае поставщика Linq to SQL дерево выражений будет преобразовано в SQL и выполнено на сервере SQL. Однако если вы используете оператор AsQueryable в запросе, который не реализует IQueryable и реализует только IEnumerable, то любые преобразования, которые вы применяете к запросу, автоматически возвращаются к спецификации IEnumerable. Это означает, что, пометив запрос с помощью AsQueryable, вы получите преимущества как Linq для SQL, так и Linq для реализации объекта. Если ваш существующий запрос реализует IQueryable, запрос преобразуется в SQL поставщиком Linq to SQL, в противном случае запрос выполняется в памяти в виде кода IL.
Ссылка здесь