Linq to Entities不会返回与foreach相同的值

时间:2015-03-06 15:03:21

标签: c# linq entity-framework

注意:我使用的是EF 6.1.2

我有一个包含特定日期可用的交易的数据库。我有一个方法应该返回当前可用的余额,但是当在EF中运行它返回的值不同于正常运行...

我的实体类看起来像这样:

public class Transaction
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    public int AmountInCents { get; set; }
    public DateTimeOffset DateAvailable { get; set; }
}

此方法返回正确的可用金额:

double GetAvailableBalance(DbProxy dbProxy, DateTimeOffset atTime)
{
    var amount = 0d;
    var transactions = dbProxy.Transactions.ToList();
    foreach (var transaction in transactions)
    {
        if (transaction.DateAvailable <= atTime)
        {
            amount += transaction.AmountInCents/100d;
        }
    }
}

此版本返回0:

double GetAvailableBalance(DbProxy dbProxy, DateTimeOffset atTime)
{
    return await dbProxy.Transactions
        .Where(t => t.DateAvailable <= atTime)
        .Select(t => t.AmountInCents / 100d)
        .Union(new[] { 0d })
        .SumAsync();
}

我很难过为什么这不起作用......有人能看出问题是什么吗?

1 个答案:

答案 0 :(得分:1)

与0结合是导致问题的原因。您应该将其更改为使用DefaultIfEmpty(),或者您可以改为Concat(new[] { 0 })

同样,我想强调一下,如果您正在处理美元金额,您可能应该使用decimal,否则您可能会遇到可能导致真钱无法解释的不稳定的数学运算为了或丢失。

double GetAvailableBalance(DbProxy dbProxy, DateTimeOffset atTime)
{
    return await dbProxy.Transactions
        .Where(t => t.DateAvailable <= atTime)
        .Select(t => t.AmountInCents / 100d)
        .DefaultIfEmpty()
        .SumAsync();
}

double GetAvailableBalance(DbProxy dbProxy, DateTimeOffset atTime)
{
    return await dbProxy.Transactions
        .Where(t => t.DateAvailable <= atTime)
        .Select(t => t.AmountInCents / 100d)
        .Concat(new[] { 0 })
        .SumAsync();
}

如果你必须使用双打,你应该至少转换为双倍作为最后一步:

    return await dbProxy.Transactions
        .Where(t => t.DateAvailable <= atTime)
        .Select(t => t.AmountInCents)
        .DefaultIfEmpty()
        .SumAsync() / 100d;