左外连接linq的结果中的空值会导致错误

时间:2016-04-04 05:48:04

标签: c# linq

我有linq查询,左外连接两个表。我发现如果一个字段的值返回null,那么我将收到一条错误消息:

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

我在下面复制了我的linq:

var SrvRef = from s in db.SrvHeads
    join r in db.Referrants on s.svhReferrer equals r.refID into r_join
    from r in r_join.DefaultIfEmpty()
    where s.svhAccID == accId &&
    s.svhHeadCnt == HeadId
    select new
    {
    s.svhBalance,
    r.refID
    };
bool FBeenPaid = SrvRef.FirstOrDefault().svhBalance == 0M; //this causes error

如何解决此问题?

3 个答案:

答案 0 :(得分:8)

我对你得到的那种错误感到有些惊讶,但是你需要考虑到结果为空的可能性两个

  • 在查询中,r可以为null。 (如果您不希望在r_join匹配s时没有元素时匹配,则不应使用左外连接。
  • 在结果中:您正在使用FirstOrDefault(),如果null为空,则会返回SrvRef

所以乍一看它应该是这样的:

var query = from s in db.SrvHeads
    join r in db.Referrants on s.svhReferrer equals r.refID into r_join
    from r in r_join.DefaultIfEmpty()
    where s.svhAccID == accId && s.svhHeadCnt == HeadId
    select new
    {
        s.svhBalance,
        refId = r == null ? 0 : r.refID // Adjust to the appropriate type of refID
    };
var result = query.FirstOrDefault();
bool beenPaid = result != null && result.svhBalance == 0m;

使用C#6,您可以将底部的两行更改为:

bool beenPaid = query.FirstOrDefault()?.svhBalance == 0m ?? false;

说完了:

  • 您目前还没有在结果中使用refId - 为什么要将其包含在结果中?
  • 您确定要进行左外连接吗?
  • 您确定首先获取 结果是否真的如此?如果加入中有多个结果怎么办?
  • 你有什么理由不在查询中做整件事吗?类似的东西:

    var paid = db.SrvHeads
                 .Where(s => s.svhAccID == accId && s.svhHeadCnt == HeadId)
                 .Any(s => db.Refererrants.Any(r => s.svhReferrer == r.refID
                         && s.svhBalance == 0m);
    

    ..但只是为了你想要的精确语义。

答案 1 :(得分:1)

我认为导致错误的是svhBalance是一个int32值类型,并且您正在访问SrvRef.FirstOrDefault()返回的空值。 请尝试以下行,并告诉我它是否对您有帮助。

如果svhBalance是int值类型

  

var SrvRefObj = SrvRef.FirstOrDefault(); bool FBeenPaid =(((SrvRefObj!= null)&&(SrvRefObj.svhBalance   != null))?(SrvRefObj.svhBalance == 0):( false))

否则,如果是小数值类型

  

var SrvRefObj = SrvRef.FirstOrDefault(); bool FBeenPaid =(((SrvRefObj!= null)&&(SrvRefObj.svhBalance   != null))?(SrvRefObj.svhBalance == 0M):( false))

答案 2 :(得分:0)

我有一个类似的问题。

原因:您使用的是r_join.DefaultIfEmpty()中“ r ”中的内容。左外部联接不能使用相同的别名。

解决方案::在DefaultIfEmpty()情况下,请使用其他别名。例如:rEmpty 我修改了以下查询及其工作方式。

var SrvRef = from s in db.SrvHeads
join r in db.Referrants on s.svhReferrer equals r.refID into r_join
from rEmpty in r_join.DefaultIfEmpty()
where s.svhAccID == accId &&
s.svhHeadCnt == HeadId
select new
{
s.svhBalance,
refID = rEmpty == null ? 0 : rEmpty.refID
};