Эффективный счет (с использованием GROUP BY) для сбора в Entity Framework - PullRequest
1 голос
/ 09 августа 2011

Я использую Entity Framework 4.1 с ASP.NET MVC 3. У меня есть две таблицы с отношением «один ко многим», скажем, Магазин и ShopVisit , и яхочу показать список магазинов с количеством посещений .Довольно просто сделать как запрос SQL, но как мне заставить Entity Framework сделать это эффективно?

Это работает:

_db.Shops.Include("Visits").ToList();


@foreach (var shop in ViewBag.Shops)
{
    Visit count: @shop.Visits.Count
}

Однако, глядя на SQL Profiler, кажется, чтозагрузка всех посещений с помощью LEFT OUTER JOIN, а это не то, что я хочу.Я только хочу рассчитывать.Конечно, я не хочу, чтобы для каждого Shop был выполнен подзапрос.Что я могу сделать, чтобы он выполнял запрос COUNT(*) ... GROUP BY?

Даже если я делаю Select следующим образом:

_db.Shops.Include("Visits").Select(s => ShopStats { Shop = s, Vists = s.Vists.Count}).ToList();

Он все еще настаивает на выполнении LEFT OUTER JOIN, который загружаетвсе посещения.

1 Ответ

1 голос
/ 09 августа 2011

В таком случае вам нужно создать собственный тип и использовать проекцию:

var data = from s in _db.Shops
           select new SomeCustomType 
               {
                   Shop = s,
                   Count = s.Visits.Count()
               };

Вы также можете сгладить SomeCustomType, чтобы он содержал все свойства Shop вместо самого магазина.Вероятно, он выполнит внутреннее левое внешнее соединение в запросе, но не будет загружать посещения приложения.

Включение или отложенная загрузка работает, как вы описали - счет будет вычисляться в памяти, поэтому все посещения должны быть загружены.

Редактировать:

Существует еще одно решение, называемое очень ленивой загрузкой.Он не поддерживается "из коробки", но вы можете расширить EF для его поддержки .В случае слишком ленивой загрузки вы не загрузите Visits, но Count вызовет запрос к базе данных, чтобы получить количество посещений.

...