【问题标题】:LINQ query to get outstanding invoices获取未结发票的 LINQ 查询
【发布时间】:2017-09-11 00:48:32
【问题描述】:

在我的实体框架应用程序中,我有一个名为 Invoice.cs 的实体,如下所示:

public class Invoice : IEntity
{
  public Invoice()
  {
    Date = DateTime.UtcNow;
    CreatedOn = DateTime.UtcNow;
  }

  public int Id { get; set; }
  public decimal Amount { get; set; }
  public decimal Discount { get; set; }
  public DateTime Date { get; set; }
  public bool IsDeleted { get; set; }
  public bool IsSaleOrderInvoice { get; set; }
  public InvoiceStatus Status { get; set; }
  public DateTime CreatedOn { get; set; }
  public DateTime? ModifiedOn { get; set; }
  public int OrderId { get; set; }
  public virtual Order Order { get; set; }
  public virtual ICollection<Payment> Payments { get; set; }
}

public enum InvoiceStatus
{
  Outstanding = 0,
  Settled = 1,
  Overpaid = 2
}

我正在尝试查询数据库以获取所有未结发票的列表。未结发票如下:

如果根据发票进行的付款总额少于发票金额,则发票未结清

在我的 LINQ 查询中,我一直在计算发票是否未结清,目前看起来像这样:

var outstandingInvoices = from inv in _context.Invoices
    where !inv.IsDeleted && inv.Date >= startDate && inv.Date <= endDate
    select inv;

startDateendDate是传入过滤结果的参数。

【问题讨论】:

  • + let total = inv.Payments.SUM(o=>o.someamount) 在 where 子句之前,这样您就可以检查 inv.Amount total

标签: c# entity-framework linq


【解决方案1】:

我假设Payment 实体有一个Amount 属性(否则您应该将其更改为适当的属性名称):

var outstandingInvoices = from inv in _context.Invoices
                          where inv.Payments.Sum(p => p.Amount) < inv.Amount
                          select inv;

您可以选择添加您现在拥有的已删除状态和发票日期的过滤器,但根据未结发票的定义,您应该检查发票是否未结。

生成的查询将如下所示:

SELECT
    result.Id,
    result.Amount,
    result.Discount,
    result.IsDeleted,
    -- etc
    FROM (SELECT
            i.Id,
            i.Amount,
            i.Discount,
            i.IsDeleted,
            -- etc
            (SELECT SUM(p.Amount) 
             FROM [dbo].[Payments] p 
             WHERE i.Id = p.Invoice_Id) AS totalPayment
          FROM [dbo].[Invoices] AS i
    )  AS result
    WHERE totalPayment < result.Amount

【讨论】:

  • 不应该将此作为条件添加到 OP 给出的剩余条件,而不是唯一条件
  • @MrinalKamboj 我已经指出可以添加其他过滤器,但问题指出 '我正在尝试查询数据库以获取 所有 未结发票的列表' - 这就是为什么我提供了获取所有未结发票的查询,并附有关于添加额外过滤器的注释
  • @SergeyBerezovskiy 刚刚曝光了另一个“陷阱”。请阅读更新后的 Q。
  • @Ciwan 原始问题中没有有关货币的信息,因此请创建新问题而不是更改问题并使所有答案无效。
【解决方案2】:

只需使用 Payments.Sum()

var result = from inv in _context.Invoices
                          where inv.Payments.Sum(payment => payment.Amount) < inv.Amount
                          select inv;

【讨论】:

  • 付款不是您要与Amount比较的小数类型
  • 不应该将其添加为 OP 给出的剩余条件,而不是唯一条件
【解决方案3】:
var outstandingInvoices = from inv in _context.Invoices
where !inv.IsDeleted && inv.Date >= startDate && inv.Date <= endDate
      && inv.Payments.Count() < inv.Amount
select inv;

在 where 子句中添加 inv.Payments.Count() &lt; inv.Amount

或者,如果您的班级中有 amount 并且您需要总结它们,请使用 inv.Payments.sum(p=&gt;p.TheAmountProperty) &lt; inv.Amount

【讨论】:

  • 为什么Count,为什么不Sum
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 1970-01-01
  • 2014-04-01
  • 1970-01-01
相关资源
最近更新 更多