我正在尝试在其中显示一些报告,其中包含一些子报告,但每次显示报告时都会抛出一些要求数据库连接的对话框。我正在使用此代码:
private void frmReporte_Load(object sender, System.EventArgs e)
{
Clave = ConfigurationSettings.AppSettings["Password"].ToString();
NombreBD = ConfigurationSettings.AppSettings["CatalogBD"].ToString();
NombreServidor = ConfigurationSettings.AppSettings["Servidor"].ToString(); ;
UsuarioBD = ConfigurationSettings.AppSettings["UserID"].ToString();
this.crtReportes.ReportSource = this.prepareReport();
}
public void imprimirReporte()
{
ReportDocument rpt = new ReportDocument();
rpt.Load(mvarRutaReporte);
rpt.SetDataSource(clsReportes.dsReporte);
rpt.PrintToPrinter(1, false, 1, 1);
}
private ReportDocument prepareReport()
{
Sections crSections;
ReportDocument crReportDocument, crSubreportDocument;
SubreportObject crSubreportObject;
ReportObjects crReportObjects;
ConnectionInfo crConnectionInfo;
Database crDatabase;
Tables crTables;
TableLogOnInfo crTableLogOnInfo;
crReportDocument = new ReportDocument();
crReportDocument.Load(RutaReporte);
crReportDocument.SetDataSource(clsReportes.dsReporte.Tables[0]);
crDatabase = crReportDocument.Database;
crTables = crDatabase.Tables;
crConnectionInfo = new ConnectionInfo();
crConnectionInfo.ServerName = NombreServidor ;
crConnectionInfo.DatabaseName = NombreBD;
crConnectionInfo.UserID = UsuarioBD;
crConnectionInfo.Password = Clave;
foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables)
{
crTableLogOnInfo = aTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
aTable.ApplyLogOnInfo(crTableLogOnInfo);
}
// Para los reportes que poseen subreportes
// pongo el objeto seccion del la seccion actual del reporte
crSections = crReportDocument.ReportDefinition.Sections;
// busco en todas las secciones el objeto reporte
foreach (Section crSection in crSections)
{
crReportObjects = crSection.ReportObjects;
//busco en todos los reportes por subreportes
foreach (ReportObject crReportObject in crReportObjects)
{
if (crReportObject.Kind == ReportObjectKind.SubreportObject)
{
crSubreportObject = (SubreportObject)crReportObject;
//abro el subreporte y me logeo con los datos del reporte general
crSubreportDocument = crSubreportObject.OpenSubreport(crSubreportObject.SubreportName);
crDatabase = crSubreportDocument.Database;
crTables = crDatabase.Tables;
foreach (CrystalDecisions.CrystalReports.Engine.Table aTable in crTables)
{
crTableLogOnInfo = aTable.LogOnInfo;
crTableLogOnInfo.ConnectionInfo = crConnectionInfo;
aTable.ApplyLogOnInfo(crTableLogOnInfo);
}
}
}
}
return crReportDocument;
}
答案 0 :(得分:2)
我遇到了类似的问题,现在已经解决了,所以我添加了这个回复,以防万一我可以帮助别人。
设置报告的SQL Server登录信息时,请确保包含服务名称。因此,例如,确保您提供Crystal“myserver \ myservice”而不仅仅是“myserver”。
我的程序只能使用“myserver”从SQL Server访问数据,但Crystal需要提供“myserver \ myservice”。
答案 1 :(得分:1)
在crystal中,您可以指定是否在Crystal Management Console(CMC)@每个报告级别提示db login @生成报告的时间。登录CMC,打开报告>处理>数据库。在页面底部,您可以指定“提示用户进行数据库登录”,“使用SSO上下文进行数据库登录”或“使用与运行报表时相同的数据库登录”。选择第三个选项以使用存储在服务器中的凭据。
答案 2 :(得分:1)
你可以写 report.SetDatabaseLogon(“username”,“pwd”,@“server”,“database”); 提供登录信息,然后在运行代码时不会出现数据库登录框。
答案 3 :(得分:0)
如果客户端或服务器禁用了相应的TLS协议版本,则使用早期版本的SQL Native Client(例如,提供程序:SQLNCLI)保存的某些较旧的Crystal Report文件将不再能够登录。例如,如果报表是使用SQL Server 2005(版本9.00.xx)保存的,则需要TLS 1.0。如果禁用此协议,则不会出现直观错误,只是会以编程方式显示“数据库登录失败”。即使该帐户可能具有适当的SQL权限,也会提示客户端软件(包括在网络浏览器中呈现的客户端软件)输入密码。
如果要在IIS应用程序中呈现报告,请参阅Nartac Software的名为IISCrypto的工具,以轻松打开和关闭各种协议,密码,哈希和密钥交换。
手动编辑报告文件并使用数据库-与更现代的本机客户端连接时设置数据源位置是解决此问题的一种方法,因此不需要保持过时和不安全的协议。