C# 如何在聚合一个值之前很久将其强制转换为?

C# 如何在聚合一个值之前很久将其强制转换为?,c#,entity-framework-core,sql-server-2017,ef-core-2.1,C#,Entity Framework Core,Sql Server 2017,Ef Core 2.1,从EF core 2.1.4开始,如果我们将int值转换为long或long?在聚合之前,为了避免算术溢出,此强制转换不会影响生成的查询,并且无论如何都会发生溢出 using Microsoft.EntityFrameworkCore; using System; using System.Linq; namespace EfCoreBugs { class Program { static void Main(string[] args) { using

从EF core 2.1.4开始,如果我们将int值转换为long或long?在聚合之前,为了避免算术溢出,此强制转换不会影响生成的查询,并且无论如何都会发生溢出

using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;

namespace EfCoreBugs
{
  class Program
  {
    static void Main(string[] args)
    {
      using (var dbContext = new MyDbContext())
      {
        Console.WriteLine(dbContext.Payments.Sum(x => (long?)x.Amount));
      }
      Console.ReadLine();
    }

    public class MyDbContext : DbContext
    {
      protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
        optionsBuilder.UseSqlServer(@"Server=.;Database=EfCoreBugs;Trusted_Connection=True;MultipleActiveResultSets=True;");
      }
      public DbSet<Payment> Payments { get; set; }
    }

    public class Payment
    {
      public int Id { get; set; }
      public int Amount { get; set; }
    }
  }
}
有没有办法解决这个溢出问题?除了将Amount的数据类型更改为long以外,请尝试Convert.ToInt64x.Amount

它可以翻译成

SELECT SUM(CONVERT(bigint, [x].[Amount])) FROM [Payments] AS [x] 
并运行无溢出


给未来的读者。这实际上取决于ORM,它可能无法在所有情况下工作

dbContext.Payments.Selectx=>longx.Amount.Sum?这行得通吗,就这么简单guess@TheGeneral否,仍然创建相同的查询。我还尝试了:dbContext.Payments.Selectx=>new{A=long?x.Amount}.Sumz=>z.A,但失败了。还尝试了Convert.ToInt64x.Amount。当然,这可能行得通,也可能行不通。解决方法是在数据库之外进行求和,当然可能会对性能产生严重影响,如dbContext.Payments.Selectx=>x.Amount.AsEnumerable.Sumx=>long?x。但我认为您希望在DB上进行求和。@general Convert.ToInt64x.Amount将[Payments]中的SUMCONVERTbigint、[x].[Amount]转换为[x],并在没有溢出的情况下运行。你能把它写下来作为答案吗?只是出于好奇:如果[Payments]表不包含任何行,或者如果[Amount]在所有行中都为null,那么对于允许null的列,生成的SQL将生成null,而C变量的类型long不支持null。在这种情况下,你会在C中看到0吗?@JeppeStigNielsen我自己也很想知道这一点,但是我想如果worstYeah遇到最坏的情况,你可以在查询中检查null,但它仍然很有趣。在.NET Framework本身中,Convert.ToInt64objectnull将成功并返回0L。如果输入int,则使用此重载?将HasValue false转换为Convert.ToInt64·。但我这里没有EF,所以我没有测试那里发生了什么。@JeppeStigNielsen是的,我在手机上,所以我也不能测试它
SELECT SUM(CONVERT(bigint, [x].[Amount])) FROM [Payments] AS [x]