Подтвердить что ты не робот

Slow foreach() в запросе LINQ - ToList() значительно повышает производительность - почему?

Я как бы понимаю всю концепцию замедленного исполнения, но следующее меня озадачивает...

В DataTable, содержащем около 1000 строк, я вызываю AsEnumerable(). Затем я выбираю объекты, возвращаемые в IEnumerable строго типизированных классов (1)... Здесь, где я запутываюсь: я делаю цикл foreach в коллекции; выбирая материал из отдельных элементов в коллекции, используя кучу Where() calls (2)... И он мертв медленно.


  • DataTable.AsEnumerable().Select(r => new ObjectRepresentation { ... });
  • item.Where(i => i.SomeEnum == SomeEnum.Something)


... Но если я вызову ToList() сразу после моего вызова AsEnumerable() в DataTable, цикл foreach займет менее секунды.

Что мне здесь не хватает? Действительно ли я вызываю AsEnumerable() каждый раз, когда цикл повторяется? Или каждый раз, когда я получаю доступ к элементу коллекции? Или каждый раз, когда я делаю вызов Where() для элемента в коллекции? Или все вышеперечисленное?





Обновление

Несколько полный код:

public class ObjectRepresentation
{
    public SomeEnum SomeEnum { get; set; }
}


var collection = DataTable.AsEnumerable().Select(r => new ObjectRepresentation
{
    SomeEnum = (SomeEnum)Convert.ToInt32(r["SomeEnum"])
});

foreach(var item in collection) // slow loop
{
    // 10 or so Where() calls on item inside this loop
}

collection = collection.ToList(); // Hit hyper speed button!

foreach(var item in collection) // fast loop
{
    // 10 or so Where() calls on item inside this loop
}
4b9b3361

Ответ 1

Он не получит все элементы из базы данных, пока вы не наберете

 ToList or First or Single

В foreach вы отправляете запрос в базу данных для каждого элемента. Таким образом, он работает медленнее. Откройте ваш профилировщик sql, чтобы лучше понять.

Ответ 2

Вы не понимаете, какие методы отложены, а какие нет, поэтому вы не понимаете, когда ваш код определяет операции и выполняет операции.

Все они отложены. Они определяют, но не выполняют операцию.

source.AsEnumerable
source.Select
source.Where

Они перечисляют источник и поэтому не откладываются.

source.ToList
source.First
source.Single
foreach(var x in source)

Ответ 3

Действительно, вы, похоже, не имеете четкого представления о том, что такое выполнение кода, и каково определение намерения (возможно) выполнить позже, когда результаты фактически используются. Я предлагаю прочитать эту часть LINQ.

И, возможно, попробуйте выполнить оба ваших варианта с прикрепленным отладчиком, чтобы вы действительно могли видеть, какой код выполняется в каком порядке и что на самом деле происходит с вашими данными. У вас может быть сюрприз (большой?) Здесь...