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

Ссылка здесь

Другие вопросы по тегам