Linq to SQL / Linq to Entities используют шаблон отложенное выполнение . Как только вы вызываете For Each
или что-то еще, что косвенно вызывает GetEnumerator
, ваш запрос переводится в SQL и выполняется с базой данных.
Хитрость в том, чтобы убедиться, что ваш запрос полностью и правильно определен, прежде чем это произойдет Используйте Where(...)
и другие фильтры Linq, чтобы максимально уменьшить объем данных, которые запрос получит. Эти фильтры встроены в один запрос до вызова базы данных.
Linq to SQL / Linq to Entities также используют Ленивая загрузка . В этом случае, если у вас есть связанные сущности (например, Заказ на продажу -> имеет много строк заказа на продажу -> имеет 1 Продукт), запрос не будет возвращать их, если он не будет знать, что это необходимо. Если вы сделали что-то вроде этого:
Dim orders = entities.SalesOrders
For Each o in orders
For Each ol in o.SalesOrderLines
Console.WriteLine(ol.Product.Name)
Next
Next
Вы получите ужасную производительность, потому что во время вызова GetEnumerator
(начало For Each) механизм запросов не знает, что вам нужны связанные сущности, поэтому «экономит время», игнорируя их. Если вы наблюдаете активность базы данных, вы увидите сотни / тысячи обращений к базе данных, поскольку каждая связанная сущность затем извлекается 1 за раз.
Чтобы избежать этой проблемы, если вы знаете, что вам понадобятся связанные сущности, используйте метод Include()
в Entity Framework. Если вы правильно поняли, при профилировании активности базы данных вы должны увидеть только один запрос, и каждый элемент, извлекаемый этим запросом, должен быть использован вашим приложением.