Оператор EF linq не генерирует вложенный счетчик выбора (*) - PullRequest
0 голосов
/ 01 октября 2019

У нас есть таблица предметов, к которой может быть прикреплено несколько изображений. Я хочу создать конечную точку, которая возвращает все элементы, а также количество изображений, прикрепленных к каждому элементу в виде json.

Я делаю это с помощью следующего оператора linq:

var items = context.Items.AsNoTracking ();
return Json (await items.Select (item => new {
    item = item,
    numImages = item.Images.Count (),
}).ToListAsync ());

Это работает, но это невероятно медленно, потому что EF генерирует отдельную инструкцию SQL для каждого элемента, например:

SELECT COUNT(*) FROM `Images` AS `q0` WHERE @_outer_IdImages = `q0`.`idImages`

Как я могу построить свой linq так, чтобы генерировался только один запрос, например:

SELECT idItems, name, (SELECT COUNT(*) FROM Images WHERE idItems = i.idItems) FROM Items i;

1 Ответ

1 голос
/ 01 октября 2019

Я обошёл проблему производительности, сгенерировав словарь Image idItems to Counts, как показано ниже:

var items = context.Items.AsNoTracking ();
var imagesDict = await context.Images.AsNoTracking ()
    .GroupBy (img => img.IdItems)
    .ToDictionaryAsync (g => g.Key, g => g.Count ());
return Json (await items.Select (item => new {
        item = item,
        numImages = imagesDict.GetValueOrDefault (item.IdItems, 0),
    }).ToListAsync ());

Это совсем не то, что я хотел, но в итоге получилось намного быстрее, потому что толькодве DbCommands выполняются. И это намного чище, чем сырой SQL

...