В чем разница между использованием предварительно инициализированного списка для итерации и использованием ienumerable / iqueryable для итерации? - PullRequest
1 голос
/ 11 октября 2019

Например, у меня есть класс CustomDataContext со следующим DbSet:

public DbSet<CustomClass> Classes { get; private set; }

В чем разница между следующими двумя случаями?

Случай 1:

using (var context = new CustomDataContext())
{
    var something = ....;
    var sql = $"SELECT * FROM dbo.mytable WHERE condition = {something}";
    var items = context.Classes.SqlQuery(sql).ToList(); // <--- ToList()

    foreach (var item in items)
    {
        ...
    }
}

Случай 2:

using (var context = new CustomDataContext())
{
    var something = ....;
    var sql = $"SELECT * FROM dbo.mytable WHERE condition = {something}";
    var items = context.Classes.SqlQuery(sql); //  <--- No ToList()

    foreach (var item in items)
    {
        ...
    }
}

Есть ли какая-либо польза от итерации непосредственно для неисчислимого / запрашиваемого объекта с точки зрения производительности? Я знаю, что происходит в случае 1, но я не знаю, что происходит в случае 2. Может кто-нибудь объяснить мне, пожалуйста?

1 Ответ

1 голос
/ 11 октября 2019

IEnumerable описывает поведение, в то время как List является реализацией этого поведения. Когда вы используете IEnumerable, вы даете компилятору возможность отложить работу на потом, возможно, оптимизируя его. Если вы используете ToList (), вы немедленно заставляете компилятор преобразовывать результаты.

В приведенном вами примере заметной разницы в производительности нет.

Производительность наступает, когда мы используем преимущество отложенного выполнения. LINQ не генерирует SQL для запроса базы данных, пока вы не перечислите его.

Рассмотрим следующий код:

public IEnumerable<Vehicles> CaliEmissionStd()
{
    return from a in EPA.RoadVehicles
           where a.emissions.CaliEmissions == true
           select a;
}

public IEnumerable<Vehicles> Cars(IEnumerable<Vehicles> vehicles)
{
    return from a in vehicles
           where a.VehType == "Car"
           select a;
}

Здесь у нас есть метод, который выбирает все дорожные транспортные средства со стандартом эмиссии cali, и фильтр, который выбирает подсписок типа car.

Поскольку LINQ удерживает построение запроса до тех пор, пока мы его не перечислим, мы можем сделать следующее, чтобы в итоге мы получили один запрос SQL, который запрашивает базу данных и возвращает только соответствующие строки.

var AutosWithCaliEmissionStd = Cars(CaliEmissionStd());

Но если бы мы вернули список из CaliEmissionStd(), то он работал бы медленнее, потому что база данных возвращала бы данные для всех транспортных средств со стандартом калибровки выбросов (автомобили, внедорожники, грузовики, мотоциклы и т. Д.) Вместопросто Автомобили, заставляя нас тратить впустую циклы / время, делая фильтрацию в клиенте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...