转换为值类型“Double”失败,因为实现值为null

时间:2013-03-08 15:50:24

标签: c# entity-framework

CODE:

double cafeSales = db.InvoiceLines
    .Where(x =>
        x.UserId == user.UserId &&
        x.DateCharged >= dateStart &&
        x.DateCharged <= dateEnd)
    .Sum(x => x.Quantity * x.Price);

错误:

转换为值类型'Double'失败,因为具体化值为null。结果类型的泛型参数或查询必须使用可空类型。

我已经看到了什么:

The cast to value type 'Int32' failed because the materialized value is null

The cast to value type 'Decimal' failed because the materialized value is null

我做过什么:

double cafeSales = db.InvoiceLines
    .Where(x =>
        x.UserId == user.UserId &&
        x.DateCharged >= dateStart &&
        x.DateCharged <= dateEnd)
    .DefaultIfEmpty()
    .Sum(x => x.Quantity * x.Price);

double? cafeSales = db.InvoiceLines
    .Where(x =>
        x.UserId == user.UserId &&
        x.DateCharged >= dateStart &&
        x.DateCharged <= dateEnd)
    .Sum(x => x.Quantity * x.Price);

这些都不奏效。我知道问题的原因是该表中没有我传入的UserId中的行。在这种情况下,我更喜欢Sum()只返回0给我。有什么想法吗?

8 个答案:

答案 0 :(得分:58)

最佳解决方案

double cafeSales = db.InvoiceLines
                     .Where(x =>
                                x.UserId == user.UserId &&
                                x.DateCharged >= dateStart &&
                                x.DateCharged <= dateEnd)
                     .Sum(x => (double?)(x.Quantity * x.Price)) ?? 0;

答案 1 :(得分:8)

您可以检查集合是否有正确的结果。

double? cafeSales = null;
var invoices = db.InvoiceLines
    .Where(x =>
        x.UserId == user.UserId &&
        x.DateCharged >= dateStart &&
        x.DateCharged <= dateEnd
    )
    .Where(x => x.Quantity != null && x.Price != null);
if (invoices.Any()) {
    cafeSales = invoices.Sum(x => x.Quantity * x.Price);
}

答案 2 :(得分:4)

我知道这有点旧,但万一它可以帮助任何人。

@Matt我想DefaultIFEmpty()方法应该适用于您,以防您为要应用Sum的列传递默认值。这个方法有一些你可能需要检查的重载,如果重载不支持你的要求,我建议使用类型转换。

 (query).DefaultIfEmpty(0) 

答案 3 :(得分:3)

这应该可以解决问题(如果QuantityPrice不可为空,则可能必须删除其中一个条件):

var cafeSales = db.InvoiceLines
    .Where(x =>
        x.UserId == user.UserId &&
        x.DateCharged >= dateStart &&
        x.DateCharged <= dateEnd &&
        x.Quantity != null &&
        x.Price != null);

double cafeSalesTotal = 0;

if (cafeSales.Any())
{
    cafeSalesTotal = cafeSales.Sum(x => x.Quantity * x.Price);
}

答案 4 :(得分:0)

 var cafeSales = db.InvoiceLines
.Where(x =>
    x.UserId == user.UserId &&
    x.DateCharged >= dateStart &&
    x.DateCharged <= dateEnd)
.Sum(x => x.Quantity * x.Price);

double i;
if(cafeSales==null) ? i=0 : i=(double)cafeSales.First();

答案 5 :(得分:0)

上述解决方案对我没有用。我的问题很相似。我确信没有返回任何行,但Sum表现得很奇怪。所以我决定在调用lambda表达式之前添加一个检查,其中我检查lambda返回的行的count属性。如果它大于零,那么我调用sum表达式。这对我有用。

答案 6 :(得分:0)

join sim in ctx.EF.Collaterals on new { id = ini.cam.id, Type = 0 } equals new 
{ id = sim.CampaignId == null ? new Guid() : sim.CampaignId, sim.Type } 
into tempcoll
from sim in tempcoll.DefaultIfEmpty()

此解决方案有效。实际上您需要使用三元运算符来检查值,并在第二列和第二个表中插入Guid(如果为null),它将起作用。 “将转换为值类型'Double'失败,因为物化值为null”将被解决 感谢

答案 7 :(得分:0)

.NET 4.0,Nullable具有“ GetValueOrDefault()”方法。 因此,如果将查询强制转换为Nullable,则完成后可以得到正确的Type。 此方法还将生成正确的单个SQL SELECT SUM查询,并且比通过linq将整个记录集返回到更高的总和的其他解决方案要快。

decimal result = ((decimal?)query.Where(w => w.Customer =="ABC").Sum(s =>  (decimal?)s.Amount)).GetValueOrDefault();