Запросить все записи, включая количество связанных записей - PullRequest
0 голосов
/ 10 апреля 2019

В приложении ASP.NET Core с Entity Framework Core отображается список записей. Поэтому все объекты коллекции извлекаются, а некоторые их свойства отображаются в таблице.

Кроме того, есть связанные сущности, связанные через внешние ключи. Для некоторых из них также должно отображаться общее количество объектов.

Например, есть следующие таблицы (упрощенно):

  • Местоположение (Id, Name, Address)
  • Устройство (Id, Name, Comment, LocationId)

Здесь показаны только местоположения (основной объект) и устройства (связанный объект), но есть и другие типы, кроме устройств. Все устройства в базе данных назначены одному местоположению. Внешние ключи и свойства навигации существуют в классах сущностей, а также в свойствах счетчика без сопоставления (см. Последний пример).

Желаемый результат таков:

  • Location Id 1, Name 1, 15 устройств в этом местоположении
  • Location Id 2, Name 2, 6 устройств в этом месте
  • Location Id 3, Name 3, 0 устройств в этом местоположении

Я мог бы просто сначала выбрать местоположения, упорядоченные по имени, а затем получить количество устройств для каждого местоположения в отдельных запросах базы данных. Это может привести к большому количеству коротких запросов.

var locations = dbContext.Locations
    .OrderBy(l => l.Name)
    .ToList();
foreach (var location in locations)
{
    int count = dbContext.Devices.Where(d => d.LocationId == location.Id).Count();
}

Я мог бы также получить все местоположения с помощью Include(location => location.Devices), а затем просто location.Devices.Count, чтобы получить их счет, но это включает в себя выборку всех деталей всех устройств, только для использования их общего количества в конце.

var locations = dbContext.Locations
    .Include(l => l.Devices)
    .OrderBy(l => l.Name)
    .ToList();
foreach (var location in locations)
{
    int count = location.Devices.Count;
}

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

var locations = dbContext.Locations
    .OrderBy(l => l.Name)
    .ToList();
var deviceCounts = dbContext.Locations
    .Select(l => new
    {
        l.Id,
        l.Devices.Count
    });
foreach (var c in deviceCounts)
{
    locations.First(l => l.Id == c.Id).DeviceCount = c.Count;
}

Я ищу запрос, чтобы выбрать местоположения, упорядоченные по имени, а также количество устройств для каждого местоположения. Результатом должен быть список типов моих сущностей, например, List<Location>. Есть ли простой или эффективный способ добиться этого с EF Core?

Ответы [ 2 ]

1 голос
/ 10 апреля 2019

Сначала создайте класс ViewModel и определите свойства, которые вы хотите отобразить в списке.ViewModel предоставит только необходимые данные, а не всю сущность.Для примера:

public class DeviceViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int DeviceCount { get; set; }
}

Затем выполните запрос, который возвращает список ViewModel, гидратированный с данными от сущности, определяющей требуемый порядок, перед методом Select.

var devices = dbContext.Locations
                       .Include(l => l.Devices)                           
                       .OrderBy(x => x.Name)          
                       .Select(l => new DeviceViewModel()
                       {
                          Id = l.Id,
                          Name = l.Name,
                          DevicesCount = l.Devices.Count()
                       })
                       .ToList();

Не забудьте вызвать ToList(), чтобы заставить ORM выполнить запрос к базе данных.

0 голосов
/ 10 апреля 2019

Вам нужно выбрать нужные значения.

var locations = dbContext.Locations
.Include(l => l.Devices)
.OrderBy(l => l.Name)
.Select( l => new {
             LocationId = l.Id,
             LocationName = l.Name,
             DeviceCount = l.Devices.Count()
        })
.ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...