【问题标题】:EF Core query where sum of relationship is less than property关系总和小于属性的 EF Core 查询
【发布时间】:2020-09-28 11:24:35
【问题描述】:

我必须上课,一类是产品类,另一类是跟踪订单。两者都存储在数据库中,我使用 ef core 作为 orm。

public class Product
{
    public int Id { get; set; }
    public int AvailableQuantity { get; set; }
    public ICollection<Order> Orders { get; set; }
}

public class Order
{
    public int Id { get; set; }
    public bool Confirmed { get; set; }
    public int Quantity { get; set; }
    public int ProductId { get; set; }
    public Product Product { get; set; }
}

现在我需要获取所有 Order.Quantity 的总和小于 Product.AvailableQuantityOrder.Confirmed 属性为 true 的产品。

我已经试过了

_context.Products.Where(product => product.Orders.Where(order => order.Confirmed).Sum(order => order.Quantity) < product.AvailableQuantity)

但这显然不起作用。我猜我需要GroupBy 的东西,但我不知道如何让这个查询工作。 另外我不想使用AsEnumerable 并在内存中执行查询,因为我的数据库很大。

【问题讨论】:

  • 不工作是什么意思?
  • 我得到一个System.InvalidOperationException 方法只能在 Type.IsGenericParameter 为 true 的类型上调用。在 System.RuntimeType.get_DeclaringMethod()
  • 你可以试试用select代替where

标签: c# linq entity-framework-core linq-to-entities


【解决方案1】:

你写道:

获取 Order.Quantity 之和小于 Product.AvailableQuantity 且 Order.Confirmed 属性为 true 的所有产品。

我认为你的意思是:

要求:获取所有已确认订单的产品,其中这些已确认订单的数量之和小于产品的可用数量。

如果您还希望最终结果中包含未确认的订单。这不会有太大变化。

var result = dbContext.Products.Where(product =>

    // keep only the Products where the sum of the confirmed orders is less than ...
    product.Orders.Where(order => order.Confirmed)
                  .Select(order => order.Quantity)
                  .Sum() < product.AvailableQuantity);

这将为您提供具有所有订单的产品:已确认的和未确认的。

如果您只想要已确认的,请考虑先使用 Select:

var productsThatCanBeDelivered = dbContext.Products.Select(product => new
{
    // Select only the product properties that you plan to use:
    Id = product.Id,
    AvailableQuantity = product.AvailableQuantity,

    ConfirmedOrders = product.Orders
        .Where(order => order.Confirmed)
        .Select(order => new
        {
            // select only the order properties that you plan to use
            Id = order.Id,
            Quantity = order.Quantity,
            ...

            // no need for this: you already know the value
            // ProductId = order.ProductId,
            // Confirmed = order.Confirmed,
        })
        .ToList(),
    })

    // keep only those Products where the quantities of the confirmed orders is less than ...
    .Where(product => product.ConfirmedOrders
                             .Select(confiredOrder => confirmedOrder.Quantity)
                             .Sum() < product.AvailableQuantity);

最后一句话:您确定您的意思是小于 AvailableQuantity,而不是小于或等于: 如果有 1 个可用产品,您只需要交付一个,为什么不交付呢?

【讨论】:

  • 谢谢,这是正确的方法并且工作正常,但是当有没有订单的产品时,这些不会显示。另外我只需要产品,不需要订单,所以你的第一个解决方案很好
  • .Sum() &lt; product.AvailableQuantity 更改为.Sum() &lt;= product.AvailableQuantity 并添加|| p.Orders.Count == 0 可以解决问题,我得到了正确的产品集。非常感谢!
【解决方案2】:
_context.Orders.Where(c => c.Confirmed).AsQueryable().GroupBy(c => c.ProductId)
               .Where(c => c.Sum(d => d.Quantity) < c.First().Product.AvailableQuantity)
               .ToDictionary(c => c.Key, c => c);

你的意思是这样的吗?

【讨论】:

  • 我厌倦了,但我得到了一个System.InvalidOperationException - “LINQ 表达式......无法翻译。”
  • 我认为问题出在需要在客户端执行的 c.First() 语句中
  • 这在使用 EF Core 版本时无法解决。 3.x 版本在 SQL 中的功能非常有限,甚至 5.x 版本目前也不是更好。
猜你喜欢
  • 2019-01-19
  • 1970-01-01
  • 2022-10-25
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多