Я как бы понимаю всю концепцию отложенного выполнения, но следующее меня озадачило ...
В DataTable, содержащем около 1000 строк, я вызываю AsEnumerable () . Затем я выбираю объекты, возвращенные в IEnumerable строго типизированных классов (1) ... Вот где я запутался: я выполняю цикл foreach для коллекции; выбор материала из отдельных элементов в коллекции с помощью набора Where () вызовов (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
}
Он не получит все элементы из базы данных, пока вы не наберете
ToList or First or Single
Foreach, вы отправляете запрос в базу данных для каждого элемента. Так он работает медленнее. Откройте профилировщик sql, чтобы лучше понять.
Вы не понимаете, какие методы откладываются, а какие нет, поэтому вы не понимаете, когда ваш код определяет операции, а когда выполняет операции.
Все они отложены. Они определяют, но не выполняют операцию.
source.AsEnumerable
source.Select
source.Where
Они перечисляют источник и поэтому не откладываются.
source.ToList
source.First
source.Single
foreach(var x in source)