在我的Entity Framework应用程序中,我有一个名为Invoice.cs
的实体,它有各种属性,但以下是我们关注的问题:
public class Invoice : IEntity
{
public int Id { get; set; }
public decimal Amount { get; set; }
public DateTime Date { get; set; }
public int OrderId { get; set; }
public virtual ICollection<Payment> Payments { get; set; }
}
我正在尝试查询数据库以获取所有未结发票的列表。未结清的发票如下:
如果针对发票的付款总额 小于发票金额,则发票 Outstanding 。
如果发票在我的LINQ查询中未完成,我就会坚持不懈地工作,目前看起来像这样:
var outstandingInvoices = from inv in _context.Invoices
where !inv.IsDeleted && inv.Date >= startDate && inv.Date <= endDate
select inv;
startDate
和endDate
是传入的参数,用于过滤结果。
与此相关的另一个复杂因素是如何进行付款。付款可以用人民币(中国货币)或英镑(英国货币)支付,在我生成的报告中,我希望所有都显示为GBP。
所以我必须以某种方式添加这个逻辑:
// loop through payments for each invoice, and add payment
// amount to a local variable called total
if (payment.Currency == Currency.Gbp)
{
total += payment.Amount;
} else
{
total += payment.Amount / (decimal)payment.ConversionRate;
}
Payment.cs
实体具有以下两个值得关注的属性:
public class PaymentViewModel
{
public int Id { get; set; }
[Required]
public decimal Amount { get; set; }
[Required]
[Display(Name = "Payment Currency")]
public Currency Currency { get; set; }
[Display(Name = "Conversion Rate")]
public float ConversionRate { get; set; }
}
答案 0 :(得分:1)
如果不在GBP中,您可以使用三元运算符来调整付款金额:
var outstandingInvoices =
from inv in _context.Invoices
let totalPayment = inv.Payments.Sum(p =>
p.Currency == Currency.Gbp ? p.Amount : p.Amount / p.ConversionRate)
where !inv.IsDeleted
&& inv.Date >= startDate && inv.Date <= endDate
&& totalPayment < inv.Amount
select inv;
答案 1 :(得分:1)
由于浮动/小数差异,您将遇到问题。根据您的数据库提供程序,它可能允许您强制从十进制转换为浮点数(或者可能不会)。当然,那么你会收到非常接近但不完全相同的付款问题。如果金额/ CoversionRate为0.999999999999999999999999999英镑,当金额为1英镑时怎么办?从技术上讲,它没有全额支付。
最终,转换率也应该是小数,而不是浮点数,但确定精度取决于您的来源。它精确到5位小数或7位?
var outstanding = _context.Invoices
.Where(x=>x.Date >= startDate)
.Where(x=>x.Date <= endDate)
.Where(x=>!x.IsDeleted)
.Where(x=>x.Payments.Sum(p=>(float)p.Amount / p.ConversionRate) < x.Amount);
或者,如果支付的总金额在1英镑以内:
var outstanding = _context.Invoices
.Where(x=>x.Date >= startDate)
.Where(x=>x.Date <= endDate)
.Where(x=>!x.IsDeleted)
.Where(x=>x.Payments.Sum(p=>(float)p.Amount / p.ConversionRate) - x.Amount < 1);