You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core中Sum()类型转换异常及无行时返回值疑问

问题描述

现有Answer和Question两个实体类,关联代码如下:

public class Answer
{
    public Guid Id { get; set; }

    public Guid? QuestionId { get; set; }
    public virtual Question? Question { get; set; }
}

public class Question
{
    public Guid Id { get; set; }

    [MaxLength(1024)] public string Question { get; set; }

    public int? MaxMarks { get; set; }
}

由于仅部分题目需要计分,MaxMarks设为可空类型。执行以下计算总分的代码时抛出异常:

TotalScore = s.Answers
                .Where(a => a.Question.MaxMarks.HasValue)
                .Sum(a => a.Question.MaxMarks)

报错信息:

System.InvalidCastException: Unable to cast object of type 'System.Int64' to type 'System.Int32'.
at Microsoft.Data.SqlClient.SqlBuffer.get_Int32()

尝试显式转换为int无效,需明确两个问题:

  1. 该异常的原因是什么?
  2. 当Sum()没有匹配行时,返回值是null还是0?

解答

一、异常原因分析

这是EF(或EF Core)处理可空整数求和时的类型映射冲突:

  • SQL Server中,SUM()函数对int类型字段计算时,默认返回bigint类型(避免累加值超出int的范围限制),但你的实体类中MaxMarks定义为int?。
  • EF尝试将SQL返回的bigint(对应C#的Int64)映射回int?(对应Int32)时,就会触发类型转换异常。
  • 你之前的显式转换无效,是因为转换时机错误:如果在LINQ查询中直接转int,EF会将转换逻辑翻译成SQL,但SQL层面的SUM结果依然是bigint,类型不匹配问题并未解决。

解决方法是先将求和目标转为可空长整型,再按需转换:

// 方式1:转为long?求和后,转成int类型结果
TotalScore = s.Answers
                .Where(a => a.Question.MaxMarks.HasValue)
                .Sum(a => (long?)a.Question.MaxMarks)
                .GetValueOrDefault();

// 方式2:直接用long?接收求和结果
long? TotalScore = s.Answers
                .Where(a => a.Question.MaxMarks.HasValue)
                .Sum(a => (long?)a.Question.MaxMarks);

二、Sum()无匹配行时的返回值

分两种情况:

  • 若对可空数值类型(如int?、long?)求和,无匹配行时返回null;
  • 若对非可空数值类型(如int、long)求和,无匹配行时返回0。
    你的代码是对int?求和,因此无匹配行时会返回null。

内容的提问来源于stack exchange,提问作者AkshatSparrow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 09:00:58