使用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
相关产品推荐
相关产品推荐

