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

在ASP.NET C#中使用LINQ计算DataTable的Sum列差值及关联场景实现

我来帮你搞定这两个在ASP.NET C#里用LINQ操作DataTable的问题,直接上实用方案:

问题1:计算DataTable中Sum(列1) - Sum(列2)的结果

要实现这个需求,核心是先把DataTable转成可枚举的行集合(用AsEnumerable()方法),然后分别计算两列的总和再做减法。这里要注意数据类型的选择,尤其是处理金额类数据时,优先用decimal避免精度丢失。

示例代码:

// 假设你的DataTable名为dt,列名是"Column1"和"Column2"
if (dt != null && dt.Rows.Count > 0)
{
    // 计算两列的总和
    var sumColumn1 = dt.AsEnumerable().Sum(r => r.Field<decimal>("Column1"));
    var sumColumn2 = dt.AsEnumerable().Sum(r => r.Field<decimal>("Column2"));
    
    // 得到最终结果
    var result = sumColumn1 - sumColumn2;
    
    // 后续可以用result做输出、赋值等操作
    Console.WriteLine($"计算结果:{result}");
}

如果你的列是int或double类型,只需要把Field<decimal>改成对应的Field<int>或Field<double>就行,但还是推荐用decimal处理财务相关数据。

问题2:给datdetail的「Opening Balance」列批量赋值

你的需求是遍历datdetail每一行,根据当前行的「Identity ID」和指定日期,在DatTemp表中筛选符合条件的行,计算Sum(Dr)-Sum(Cr)后赋值给「Opening Balance」。我先补全你给出的代码,再给你一个性能更优的版本。

基础实现(补全你的代码)

先把日期转换提出来避免重复操作,然后完成计算逻辑:

// 先把TxtFromDate的日期转成DateTime类型,避免循环里重复转换
DateTime fromDate = Convert.ToDateTime(TxtFromDate.Text.Trim());

for (int i = 0; i < datDetail.Rows.Count; i++)
{
    int currentIdentityId = Convert.ToInt32(datDetail.Rows[i]["Identity ID"]);
    
    // 筛选符合条件的行,分别计算Dr和Cr的总和
    var totalDr = DatTemp.AsEnumerable()
                         .Where(r => r.Field<int>("Identity ID") == currentIdentityId 
                                     && r.Field<DateTime>("Date") <= fromDate)
                         .Sum(r => r.Field<decimal>("Dr"));
    
    var totalCr = DatTemp.AsEnumerable()
                         .Where(r => r.Field<int>("Identity ID") == currentIdentityId 
                                     && r.Field<DateTime>("Date") <= fromDate)
                         .Sum(r => r.Field<decimal>("Cr"));
    
    // 赋值给Opening Balance列
    datDetail.Rows[i]["Opening Balance"] = totalDr - totalCr;
}

性能优化版本

上面的写法虽然能实现需求,但如果DatTemp和datdetail的行数较多,每次循环都要遍历整个DatTemp,性能会很差。咱们可以提前缓存DatTemp的分组结果,减少重复遍历:

// 先验证日期输入合法性,避免转换异常
if (!DateTime.TryParse(TxtFromDate.Text.Trim(), out DateTime fromDate))
{
    // 这里可以加用户提示,比如"请输入正确的日期格式"
    return;
}

// 提前处理DatTemp,按Identity ID分组并缓存截止日期前的Dr、Cr总和
var balanceCache = DatTemp.AsEnumerable()
                          .Where(r => r.Field<DateTime>("Date") <= fromDate)
                          .GroupBy(r => r.Field<int>("Identity ID"))
                          .ToDictionary(
                              group => group.Key,
                              group => new 
                              { 
                                  TotalDr = group.Sum(r => r.Field<decimal>("Dr")),
                                  TotalCr = group.Sum(r => r.Field<decimal>("Cr"))
                              }
                          );

// 遍历datdetail赋值,直接从缓存取数据
foreach (DataRow row in datDetail.Rows)
{
    int identityId = Convert.ToInt32(row["Identity ID"]);
    decimal openingBalance = 0;
    
    // 用TryGetValue避免找不到对应ID时的异常
    if (balanceCache.TryGetValue(identityId, out var balanceData))
    {
        openingBalance = balanceData.TotalDr - balanceData.TotalCr;
    }
    
    row["Opening Balance"] = openingBalance;
}

优化点说明

  • 只遍历一次DatTemp,把结果缓存到字典里,后续直接查询字典,时间复杂度从O(n*m)降到O(n+m)(n是DatTemp行数,m是datdetail行数)
  • 用foreach遍历DataRow比for循环更简洁直观
  • 加了DateTime.TryParse处理日期格式错误的情况,代码更健壮
  • 用TryGetValue避免找不到对应Identity ID时抛出异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:18:50