C# 转换为值类型“Double”失败,因为具体化值为 null

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15297925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 16:21:26  来源:igfitidea点击:

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

c#entity-framework

提问by Matt

CODE:

代码:

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

ERROR:

错误:

The cast to value type 'Double' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.

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

WHAT I HAVE SEEN ALREADY:

我已经看到的:

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

转换为值类型 'Int32' 失败,因为具体化值为 null

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

转换为值类型“十进制”失败,因为具体化值为空

WHAT I HAVE TRIED:

我试过的:

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

And:

和:

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

Neither of these work. I know the cause of the problem is that there are no rows in that table for the UserId I am passing in. In that case, I would prefer Sum() just returned a 0 to me. Any ideas?

这些都不起作用。我知道问题的原因是该表中没有我传入的 UserId 的行。在这种情况下,我希望 Sum() 只返回 0 给我。有任何想法吗?

回答by Maarten

You can check if the collection has any correct results.

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

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);
}

回答by James

 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();

回答by Adrian Thompson Phillips

This should do the trick (you may have to remove one of the conditions if either Quantityor Priceare not nullable):

这应该可以解决问题(如果任一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);
}

回答by Jayant Shelke

I know this is a bit old but just in case it helps anyone.

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

@Matt I guess the DefaultIFEmpty()method should work for you just in case you pass a default value for the column that you are applying Sumonto. This method has some overloads which you might want to check and I suggest type-casting if overloads do not support your requirement.

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

 (query).DefaultIfEmpty(0) 

回答by Jitendra Pancholi

Best Solution

最佳解决方案

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

回答by Bryida

The solutions above didn't work for me. My problem was similar. I was sure that no rows were being returned but Sum behaves in some strange way. So I decided to add a check just before calling the lambda expression where I check for count property of rows returned by the lambda. If it is greater than zero, then I call the sum expression. That worked for me.

上面的解决方案对我不起作用。我的问题是类似的。我确信没有返回任何行,但 Sum 的行为方式有些奇怪。所以我决定在调用 lambda 表达式之前添加一个检查,在那里我检查 lambda 返回的行的计数属性。如果它大于零,那么我调用 sum 表达式。那对我有用。

回答by testing account

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()

This solution works.Actually You need to use ternary operator to check the value and insert Guid if null in the second column and in the second table.and it will work. "The cast to value type 'Double' failed because the materialized value is null" will be solved Thanks

此解决方案有效。实际上,您需要使用三元运算符来检查值,如果在第二列和第二个表中为 null,则插入 Guid。它会起作用。“由于物化值为空,转换为值类型‘Double’失败”将得到解决谢谢

回答by Mike

.NET 4.0, Nullable has a "GetValueOrDefault()" method. So if you cast the query to Nullable, then you can end up with the correct Type when complete. This method will also generate the correct single SQL SELECT SUM query and is faster than other solutions that return the entire recordset to later sum via linq

.NET 4.0,Nullable 有一个“GetValueOrDefault()”方法。因此,如果您将查询转换为 Nullable,那么您可以在完成后得到正确的类型。此方法还将生成正确的单个 SQL SELECT SUM 查询,并且比通过 linq 将整个记录集返回到稍后求和的其他解决方案更快

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