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

如何用LINQ实现主表扣除多日志表累计工时的计算

LINQ查询修正方案:计算用户剩余工时

原代码存在的问题

  • 提前调用ToList()会把两张表的全量数据加载到内存,浪费数据库的聚合计算能力,性能低下
  • 直接关联两张表会返回多条结果(每条日志对应一条),没有对用户的完成工时做累加计算,不符合需求
  • 试图用GoalHours实体接收结果,但该实体没有Completed和Remaining属性,编译直接报错
  • 没有过滤日志表的用户范围,会关联到其他用户的工时记录

修正后的LINQ代码

方案1:查询表达式写法

var userId = 4;
var result = from gh in db.GoalHours
             where gh.UserID == userId
             join ah in db.AccumulatedHours
             on gh.ID equals ah.GH_ID into ahGroup
             select new 
             {
                 ID = gh.ID,
                 User = gh.User, // 假设GoalHours有User字段
                 Target = gh.Target,
                 Completed = ahGroup.Sum(x => x.Completed) ?? 0, // 累加完成工时,无日志时返回0
                 Remaining = gh.Target - (ahGroup.Sum(x => x.Completed) ?? 0)
             };

// 获取单个用户的结果
var userRemainingHours = result.FirstOrDefault();

方案2:方法链写法(更简洁)

var userId = 4;
var userRemainingHours = db.GoalHours
    .Where(gh => gh.UserID == userId)
    .GroupJoin(
        db.AccumulatedHours,
        gh => gh.ID,
        ah => ah.GH_ID,
        (gh, ahGroup) => new 
        {
            ID = gh.ID,
            User = gh.User,
            Target = gh.Target,
            Completed = ahGroup.Sum(x => x.Completed) ?? 0,
            Remaining = gh.Target - (ahGroup.Sum(x => x.Completed) ?? 0)
        })
    .FirstOrDefault();

关键说明

  • 使用GroupJoin而非普通Join,可以将当前目标的所有日志记录分组,方便做累加计算
  • 用Sum(x => x.Completed)统计累计完成工时,加上?? 0处理用户无日志记录的情况(避免null值报错)
  • 不提前调用ToList(),让LINQ to SQL将查询转换为SQL语句在数据库执行,性能更优
  • 使用匿名类(或自定义DTO)接收结果,避免修改原实体类结构

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 08:42:09