Ответ 1
То, что вы описываете, не является проблемой N + 1. Примером проблемы с N + 1 является здесь. N + 1 означает, что вы выполняете N + 1, а не один (или два). В вашем примере это, скорее всего, означает:
// Lazy loads all N Orders in single select
foreach(var order in MyAccount.Orders)
{
// Lazy loads all Items for single order => executed N times
foreach(var orderItem in order.Items)
{
...
}
}
Это легко решить:
// Eager load all Orders and their items in single query
foreach(var order in context.Accounts.Include("Orders.Items").Where(...))
{
...
}
Ваш пример выглядит верным для меня. У вас есть коллекция, которая предоставляет IEnumerable
, и вы выполняете на ней операцию Count
. Коллекция ленив загружена, и подсчет выполняется в памяти. Возможность перевода запроса Linq к SQL доступна только на IQueryable
с деревьями выражений, представляющими запрос. Но IQueryable
представляет запрос = каждый доступ означает новое выполнение в БД, так, например, проверка цикла Count в цикле будет выполнять запрос БД на каждой итерации.
Так что это больше о реализации динамического прокси.
Подсчет связанных объектов без их загрузки уже возможен в CTP5 первого кода (окончательная версия будет называться EF 4.1) при использовании DbContext
вместо ObjectContext
, но не путем прямого взаимодействия с коллекцией. Вам нужно будет использовать что-то вроде:
int count = context.Entry(myAccount).Collection(a => a.Orders).Query().Count();
Query
метод возвращает готовый IQueryable
, который, вероятно, работает EF, если вы используете ленивую загрузку, но можете изменить запрос - здесь я использовал Count
.