SAP Crystal Report生产环境子报表Symptom/s无数据如何解决
水晶报表生产环境Symptom/s子报表无数据解决方案
问题描述
现有包含5个子报表的主报表,开发环境预览所有子报表数据正常,生产环境仅Symptom/s子报表无数据输出。
开发环境效果:
生产环境效果:
原报表加载代码:
private void loadReport(Int64 appointmentID) { try { rd = new ReportDocument(); //加载主报表患者数据 SqlCommand cmd1 = new SqlCommand("st_getPatientBill", MainClass.con); cmd1.CommandType = CommandType.StoredProcedure; cmd1.Parameters.AddWithValue("@appID", appointmentID); SqlDataAdapter da1 = new SqlDataAdapter(cmd1); DataTable dt1 = new DataTable(); da1.Fill(dt1); rd.Load(Application.StartupPath + "\\Reports\\PrescriptionReport.rpt"); rd.SetDataSource(dt1); ConnectionInfo ci = new ConnectionInfo(); ci.DatabaseName = "cms"; ci.UserID = "sa"; ci.Password = "12345"; ci.ServerName = "DESKTOP-753VMJS"; Tables tables = rd.Database.Tables; //加载内部用药数据 SqlCommand cmd4 = new SqlCommand("st_getInternalMedicine", MainClass.con); cmd4.CommandType = CommandType.StoredProcedure; cmd4.Parameters.AddWithValue("@appID", appointmentID); SqlDataAdapter da4 = new SqlDataAdapter(cmd4); DataTable dt4 = new DataTable(); da4.Fill(dt4); rd.Subreports[0].SetDataSource(dt4); //加载外部用药数据 SqlCommand cmd3 = new SqlCommand("st_getExternalMedicine", MainClass.con); cmd3.CommandType = CommandType.StoredProcedure; cmd3.Parameters.AddWithValue("@appID", appointmentID); SqlDataAdapter da3 = new SqlDataAdapter(cmd3); DataTable dt3 = new DataTable(); da3.Fill(dt3); rd.Subreports[0].SetDataSource(dt3); //加载疾病数据 SqlCommand cmd5 = new SqlCommand("st_getPatientDiseaseWRTAppointment", MainClass.con); cmd5.CommandType = CommandType.StoredProcedure; cmd5.Parameters.AddWithValue("@appID", appointmentID); SqlDataAdapter da5 = new SqlDataAdapter(cmd5); DataTable dt5 = new DataTable(); da5.Fill(dt5); rd.Subreports[0].SetDataSource(dt5); //加载症状数据 SqlCommand cmd6 = new SqlCommand("st_getPatientSymptomsWRTAppointment", MainClass.con); cmd6.CommandType = CommandType.StoredProcedure; cmd6.Parameters.AddWithValue("@appID", appointmentID); SqlDataAdapter da6 = new SqlDataAdapter(cmd6); DataTable dt6 = new DataTable(); da6.Fill(dt6); rd.Subreports[0].SetDataSource(dt6); //加载检验数据 SqlCommand cmd7 = new SqlCommand("st_getPatientTestWRTAppointment", MainClass.con); cmd7.CommandType = CommandType.StoredProcedure; cmd7.Parameters.AddWithValue("@appID", appointmentID); SqlDataAdapter da7 = new SqlDataAdapter(cmd7); DataTable dt7 = new DataTable(); da7.Fill(dt7); rd.Subreports[0].SetDataSource(dt7); //配置主报表数据库登录信息 foreach (CrystalDecisions.CrystalReports.Engine.Table table in tables) { TableLogOnInfo tableLogonInfo = table.LogOnInfo; tableLogonInfo.ConnectionInfo = ci; table.ApplyLogOnInfo(tableLogonInfo); } crystalReportViewer1.ReportSource = rd; crystalReportViewer1.RefreshReport(); } catch (Exception ex) { if (rd != null) { rd.Close(); } } }
核心问题
- 所有子报表的数据源都绑定到了
Subreports[0],后赋值的数据源会覆盖之前的内容,最终只有最后一个绑定的检验子报表拿到了代码赋值的数据源,其余子报表相当于没有通过代码绑定数据。开发环境能正常显示是因为硬编码的数据库连接和本地环境匹配,子报表通过内置连接逻辑自动拉取了数据,生产环境服务器名、账号密码和开发环境不一致,子报表无法自主连库拉数,只能用代码绑定的数据源,所以症状子报表无数据。 - 仅配置了主报表的数据库登录信息,没有给子报表配置登录信息,生产环境子报表无法自主连接数据库。
- 数据库连接信息硬编码,无法适配生产环境的数据库配置。
修复步骤
- 打开主报表文件
PrescriptionReport.rpt,确认5个子报表的排列顺序,记录每个子报表对应的索引(从0开始计数),常规顺序参考:内部用药对应0、外部用药对应1、疾病对应2、症状对应3、检验对应4。 - 修改每个子报表的数据源绑定逻辑,替换为对应索引:
// 内部用药 rd.Subreports[0].SetDataSource(dt4); // 外部用药 rd.Subreports[1].SetDataSource(dt3); // 疾病 rd.Subreports[2].SetDataSource(dt5); // 症状 rd.Subreports[3].SetDataSource(dt6); // 检验 rd.Subreports[4].SetDataSource(dt7);
- 新增子报表数据库登录配置,在主报表表遍历逻辑后添加如下代码:
// 配置所有子报表的数据库登录信息 foreach (ReportDocument subReport in rd.Subreports) { foreach (CrystalDecisions.CrystalReports.Engine.Table table in subReport.Database.Tables) { TableLogOnInfo tableLogonInfo = table.LogOnInfo; tableLogonInfo.ConnectionInfo = ci; table.ApplyLogOnInfo(tableLogonInfo); } }
- 将硬编码的数据库连接信息改为从配置文件读取,适配开发、生产不同环境的数据库配置。
验证方法
先在代码中给dt6加断点,确认dt6是否有数据:如果dt6有数据,修复绑定索引即可;如果dt6无数据,检查生产环境中存储过程st_getPatientSymptomsWRTAppointment的执行权限、入参是否正常。
内容的提问来源于stack exchange,提问作者Ali Raza
相关产品推荐
相关产品推荐

