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

LINQ查询SQLite时decimal类型Sum聚合报错,求解决方法

解决SQLite EF Core中decimal类型Sum聚合报错问题

问题背景

在使用EF Core查询SQLite数据库时,对decimal类型字段执行Sum聚合操作报错:

System.NotSupportedException: SQLite cannot apply aggregate operator 'Sum' on expressions of type 'decimal'. Convert the values to a supported type, or use LINQ to Objects to aggregate the results on the client side.

尝试显式转换decimal无效,需针对性解决。


解决方案

方案1:拉取数据到客户端内存后聚合(推荐,保留精度)

SQLite不支持数据库端对decimal的Sum操作,但LINQ to Objects(内存中)支持。先将符合条件的订单数据拉取到客户端,再执行分组聚合:

[HttpGet]
public async Task<ActionResult<IEnumerable<ManagerAnalysis>>> GetManagerAnalysis()
{
    if (_context.Orders == null)
    {
        return NotFound();
    }

    // 先过滤近1个月的订单,仅选择需要的字段减少传输量
    var recentOrders = await _context.Orders
        .Where(o => o.OrderTime > DateTime.Now.AddMonths(-1))
        .Select(o => new 
        {
            ManagerId = o.Manager.Id,
            ManagerName = o.Manager.Name,
            o.TotalPrice
        })
        .ToListAsync(); // 拉取到客户端内存

    // 内存中分组统计
    var analysis = recentOrders
        .GroupBy(o => o.ManagerId)
        .Select(g => new ManagerAnalysis
        {
            ManagerName = g.First().ManagerName,
            OrderCount = g.Count(),
            OrdersPrice = g.Sum(p => p.TotalPrice)
        });

    return Ok(analysis);
}

优势:完全保留decimal的精度,避免浮点型精度损失;仅拉取必要字段,减少数据传输开销。


方案2:修改字段类型为double(适合精度要求低的场景)

将Order类的TotalPrice改为double类型,SQLite支持对double的Sum操作:

public class Order
{
    public ulong Id { get; set; }
    public Manager Manager { get; set; } = new Manager();
    public double TotalPrice { get; set; } // 替换为double
    public DateTime OrderTime { get; set; }
}

// 同时调整ManagerAnalysis对应属性类型(或转换)
public class ManagerAnalysis
{
    public string? ManagerName { get; set; }
    public int OrderCount { get; set; }
    public double OrdersPrice { get; set; } = 0;
}

注意:double是浮点型,处理金额可能存在精度损失,仅适合对精度要求不高的业务场景。


方案3:使用原生SQL查询

直接编写SQL语句执行聚合,绕开EF Core的类型转换限制:

[HttpGet]
public async Task<ActionResult<IEnumerable<ManagerAnalysis>>> GetManagerAnalysis()
{
    if (_context.Orders == null)
    {
        return NotFound();
    }

    var oneMonthAgo = DateTime.Now.AddMonths(-1);
    var analysis = await _context.Set<ManagerAnalysis>()
        .FromSqlRaw(@"
            SELECT m.Name AS ManagerName,
                   COUNT(o.Id) AS OrderCount,
                   SUM(o.TotalPrice) AS OrdersPrice
            FROM Orders o
            INNER JOIN Managers m ON o.ManagerId = m.Id
            WHERE o.OrderTime > {0}
            GROUP BY o.ManagerId", oneMonthAgo)
        .ToListAsync();

    return Ok(analysis);
}

说明:需确保ManagerAnalysis的属性名与SQL返回的列名一致,或通过[Column]特性映射;此方案在数据库端完成聚合,性能更优(大数据量场景)。


内容的提问来源于stack exchange,提问作者Mr. Luo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:55:36