Entity Framework получает SUM из дочернего свойства - PullRequest
1 голос
/ 13 апреля 2020

У меня есть следующая модель, в которой я хотел бы получить сумму всех OrderTotalItems для всех заказов клиента, где OrderTotalType (Enumeration) равен "total" или 99:

public class Customer
{
    ...
    public ICollection<Order> Orders { get; set; } = new Collection<Order>();
}

public class Order
{
    ...
    public ICollection<OrderTotalItem> OrderTotalItems { get; set; } = new Collection<OrderTotalItem>();
}

public class OrderTotalItem
{
    [Required]
    public int Id { get; set; }
    [Required]
    [Column(TypeName = "decimal(10, 4)")]
    public decimal Value { get; set; }
    [Required]
    public OrderTotalType Type { get; set; }
}

Я создание CustomerAdminDTO для включения всех соответствующих данных клиента для клиента администратора:

public class CustomerAdminDto
{
    public int Id { get; set; }
    public string UserId { get; set; }
    public Gender Gender { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string VATId { get; set; } = "";
    public bool VATIdValid { get; set; } = false;
    public DateTime Added { get; set; }
    public DateTime LastModified { get; set; }
    public decimal OrdersTotal { get; set; }
    public CustomerStatusShortDto CustomerStatus { get; set; }
    public CustomerAddressDto CustomerAddress { get; set; }
    public CustomerAddressDto BillingAddress { get; set; }
    public ICollection<OrderListShortDto> Orders { get; set; }
}

В своей службе данных я заполняю DTO следующим образом

var customerAdmin = await _context.Customers
    .Include(x => x.Addresses)
    .Include(x => x.CustomerStatus)
    .Include(x => x.Orders)
        .ThenInclude(x => x.OrderTotalItems)
    .Where(x => x.UserId == userid)
    .Select(customer => new CustomerAdminDto 
    {
        Id = customer.Id,
        UserId = customer.UserId,
        Gender = customer.Gender,
        FirstName = customer.FirstName,
        LastName = customer.LastName,
        VATId = customer.VATId,
        VATIdValid = customer.VATIdValid,
        Added = customer.Added,
        LastModified = customer.LastModified,
        OrdersTotal = customer.Orders.Sum(x => x.OrderTotalItems
            .Where(x => x.Type == Enums.OrderTotalType.Total)
            .Sum(x => x.Value)),
        CustomerStatus = new CustomerStatusShortDto
        {
            Id = customer.CustomerStatus.Id,
            Name = customer.CustomerStatus.Name,
        },
    ...
    }
    .FirstOrDefaultAsync();

, где все работает, кроме OrdersTotal.

API компилируется нормально, но выдает следующую ошибку во время выполнения:

Microsoft.Data.SqlClient.SqlException (0x80131904): Невозможно выполнить агрегатную функцию для выражения, содержащего агрегат или подзапрос.

Спасибо за ваши подсказки!

1 Ответ

1 голос
/ 13 апреля 2020

Невозможно выполнить агрегатную функцию для выражения, содержащего агрегат или подзапрос.

Эта ошибка на сервере SQL означает, что вы пытались вызвать функцию агрегирования (customer.Orders.Sum() в в вашем случае) на другое выражение, содержащее функцию агрегирования (.Sum(x => x.Value) в вашем случае) Чтобы избежать этого, вы можете упростить выражение LINQ для OrdersTotal:

OrdersTotal = customer.Orders.SelectMany(o => o.OrderTotalItems).Where(x => x.Type == Enums.OrderTotalType.Total).Sum(x => x.Value)

Здесь только одна агрегация, поэтому она должна нормально работать

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...