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

使用foreach遍历列表取distinct值生成PDF发票时取值异常问题

问题原因

  • 逻辑嵌套错误

你将分组、遍历生成PDF的代码全部写在了foreach (DataRow dr in ds.Tables[0].Rows)循环内部,每读取一行原始数据就会重复执行一次分组、遍历属性、生成PDF的逻辑,重复生成的PDF会不断覆盖之前的文件,最终留存的内容完全取决于最后一次循环的执行结果。

  • 反射遍历逻辑不符合需求

你复制的遍历PaidTrip类所有属性的代码完全没必要:你需要的仅仅是LicenseHolderID这一个属性的值,但foreach (var LicenseHolderID in PaidTrips.GetType().GetProperties())会遍历PaidTrip的所有属性(包括LicenseHolderID、Value1、Value2、Value3),每次循环都会把当前属性的值赋值给n,然后覆盖保存PDF,最终PDF里的内容就是最后一次遍历到的属性的值,自然会出现随机的其他字段值。
你提到MessageBox可以显示正确值,是因为弹窗会阻塞后续循环执行,你只看到了第一次遍历到LicenseHolderID属性时的弹窗结果,后续循环的覆盖逻辑你没有感知到。

  • DataRow索引取值错误

你从DataRow取数给PaidTrip赋值时索引设置错误:你存储过程返回的列顺序是ID(列索引0)、LicenseHolderID(列索引1)、Value1(列索引2)、Value2(列索引3)、Value3(列索引4),但你写的是LicenseHolderID = dr[0].ToString(),实际取到的是ID列的值,不是你要的持证方ID。

修正后的核心代码示例

using (SqlConnection con = new(ConnectionString.connectionString))
using (SqlCommand cmd = new("spCreateInvoice", con) {CommandType = CommandType.StoredProcedure})
using (SqlDataAdapter da = new(cmd))
using (DataTable dt = new("tblTripsPerMonth")) 
using (DataSet ds = new()) {

    con.Open();
    da.Fill(dt);
    ds.Tables.Add(dt);

    // 先把所有数据加载到集合中,这一步要放到行遍历外面
    foreach (DataRow dr in ds.Tables[0].Rows) {
       PaidTrips.Add(new PaidTrip {
             // 修正索引,取第二列的值作为LicenseHolderID
             LicenseHolderID = dr[1].ToString(),
             Value1 = (decimal)dr[2],
             Value2 = (decimal)dr[3],
             Value3 = dr[4].ToString(),
        });
    }

    // 分组去重逻辑也放到行遍历外面,只执行一次
    List<PaidTrip> distinctPaidTrips = PaidTrips
        .GroupBy(p => p.LicenseHolderID)
        .Select(g => g.First())
        .ToList();
    
    System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
    foreach (PaidTrip trip in distinctPaidTrips) {
        // 不需要反射遍历所有属性,直接取LicenseHolderID的值
        string licenseHolderName = trip.LicenseHolderID;
        
        PdfDocument pdf = new();
        PdfPage page = pdf.AddPage();
        XGraphics gfx = XGraphics.FromPdfPage(page);
        gfx.DrawString(licenseHolderName, new XFont("Arial", 40, XFontStyle.Bold), myColor, new XPoint(40, 250));
        // 后续你要生成多份的话,这里文件名带上licenseHolderName即可避免覆盖
        pdf.Save($"C:\\File\\Path\\{licenseHolderName}_Invoice.pdf");
    }
}

内容的提问来源于stack exchange,提问作者Ole M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 06:15:06