【问题标题】:Problem with LINQ to Entities query using Sum on child object property在子对象属性上使用 Sum 的 LINQ to Entities 查询问题
【发布时间】:2011-04-18 09:22:47
【问题描述】:

鉴于此查询:

from s in services
select new
{
    s.Id,
    s.DateTime,
    Class = s.Class.Name,
    s.Location,
    s.Price,
    HeadCount = s.Reservations.Sum(r => r.PartySize), // problem here. r.PartySize is int
    s.MaxSeats
}

如果服务没有任何保留,则抛出此异常:

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

我明白了,但是我应该怎么处理呢?我的意图是,如果没有保留,则将 HeadCount 分配为 0。

【问题讨论】:

    标签: c# .net linq entity-framework orm


    【解决方案1】:

    还有一个更简单的解决方案:

    from s in services
    select new
    {
        s.Id,
        s.DateTime,
        Class = s.Class.Name,
        s.Location,
        s.Price,
        HeadCount = (int?)s.Reservations.Sum(r => r.PartySize), 
        s.MaxSeats
    }
    

    注意演员表。这也可能产生比@Ahmad 的建议更简单的 SQL。

    本质上,您只是在帮助进行类型推断。

    【讨论】:

    • 根据 OP,Reservations 可能是 null,因此无法尝试在 null 上调用 Sum(...)。转换为 int? 不会绕过运行时发生的空异常。也许您正在考虑直接转换 null 值,例如 (int?)r.PartySize
    • @Ahmad,这对于 L2E 是不正确的,尽管它对于 L2O 是正确的。他们有不同的规则。不,我没有考虑铸造价值。试试我建议的代码;它确实有效。
    • +1 我忽略了为此 LINQ 提供程序进行的翻译。
    • 尽管谈论什么是“保留” 是可疑的,因为它已被翻译并且对应得不是很好,但请注意,从 .NET 的角度来看,它不是 null 而是一个空可枚举。因此,尽管检查 null 有效(因为 L2E 特性)它实际上并没有多大意义......
    • 谢谢! - 尽管假设 Headcount 不可为空,但该行应该是 HeadCount = (int?)s.Reservations.Sum(r => r.PartySize) ?? 0,
    【解决方案2】:

    你应该检查一下:

    HeadCount = s.Reservations != null ? s.Reservations.Sum(r => r.PartySize) : 0,
    

    【讨论】:

    • 我在尝试之前发布了这个问题,只是因为我认为 LINQ to Entites 无法将其转换为 SQL 或类似的东西。我仍然习惯于 L2E,它似乎比 LINQ to SQL 更挑剔,关于你在 LINQ 语句中实际可以做的事情。无论如何,这是可行的,永远不要假设。谢谢。
    • @Ronnie 很高兴它成功了。它们肯定是不同的,我想 L2E 在未来只会变得更加灵活。
    • @Ronnie, @Craig:我阅读问题的方式我理解Reservations 本身可能为空。然而,我确实遇到了这个blog post,它显示了一个 EF 1.0 问题,对空集求和。该解决方案涉及强制转换为可空值并使用空值合并运算符。只是想我会提到它,以防我忽略了什么。我认为这个问题自 EF1.0 以来已经修复。
    • 您需要根据如何将其转换为 SQL 来考虑这一点,而不是根据 C# 的规则。 L2E 的游戏规则与 L2O 不同。 L2E 中没有空引用异常之类的东西,因为空值会自动合并。
    • @Craig 谢谢,这是有道理的,因为它已被翻译。我确实在考虑 L2O/C#。
    【解决方案3】:

    这应该可以解决您的问题: 尝试将int 花费到int?

    from s in services
    select new
    {
        s.Id,
        s.DateTime,
        Class = s.Class.Name,
        s.Location,
        s.Price,
        HeadCount = s.Reservations.Sum(r => (int?) r.PartySize),
        s.MaxSeats
    };
    HeadCount = HeadCount ?? 0;
    

    【讨论】:

      【解决方案4】:

      一个简单的三元运算符应该可以很好地解决这个问题...

      类似这样的:

      HeadCount = (s.Reservations != null && s.Reservations.Any()) ? s.Reservations.Sum(r => r.PartySize) : 0;
      

      这将同时处理 null 和空的情况

      【讨论】:

      • 我认为代码甚至不会编译(缺少())。它肯定不会产生高效的 SQL(当你的意思是 Any() 时,永远不要使用 .Count() == 0),但与此相比,它既低效又难以阅读。 L2E 的内置空值合并)。
      • 你是对的,它不会编译,因为 Count 缺少 '()'。匆匆写下-_-。 Any 也会更有效率。谢谢指正!
      猜你喜欢
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 2020-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-09
      相关资源
      最近更新 更多