Crystal 报告在不同环境中登录失败
Crystal Reports Log On Failed in Different Environment
我们有几个环境:
- 发展
- 蔚蓝
- 本地
Crystal报表从SQL服务器拉取数据,但数据库因环境不同而不同。
项目中有一个名为 connectionStrings.config
的配置文件,我们用于网站的连接字符串存储在那里。文件内容如下所示:
<connectionStrings>
<add name="dataModel" connectionString="data source=...;initial catalog=...;user id=...;password=...;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
为了加载报告,我设置了以下 class:
public class CrystalReportUtil
{
static string ReportsDirectory = ConfigurationManager.AppSettings["ReportsDirectory"];
private static string ConnectionString = ConfigurationManager.ConnectionStrings["dataModel"].ConnectionString;
public static ReportDocument GetReport(string reportName)
{
var report = new ReportDocument();
var fileDirectory = $"{Utilities.GetProjectRoot()}/Reports";
if (System.Web.HttpContext.Current != null)
{
fileDirectory = System.Web.HttpContext.Current.Server.MapPath(ReportsDirectory);
}
string file = Path.Combine(fileDirectory, $"{reportName}.rpt");
if (!File.Exists(file))
{
throw new System.Exception($"Unable to find report file: {file}");
}
report.Load(file);
var builder = new SqlConnectionStringBuilder(ConnectionString);
var dataSource = builder.DataSource;
var user = builder.UserID;
var password = builder.Password;
var database = builder.InitialCatalog;
RecursivelyRemapConnection(report, user, password, dataSource, database);
report.VerifyDatabase();
return report;
}
private static void RecursivelyRemapConnection(ReportDocument report, string username, string password, string server, string database)
{
foreach (IConnectionInfo connection in report.DataSourceConnections)
{
connection.SetLogon(username, password);
connection.SetConnection(server, database, false);
}
report.SetDatabaseLogon(username, password);
foreach (Table table in report.Database.Tables)
{
table.LogOnInfo.ConnectionInfo.ServerName = server;
table.LogOnInfo.ConnectionInfo.DatabaseName = database;
table.LogOnInfo.ConnectionInfo.UserID = username;
table.LogOnInfo.ConnectionInfo.Password = password;
table.LogOnInfo.ConnectionInfo.IntegratedSecurity = false;
}
if (!report.IsSubreport)
{
foreach (ReportDocument subreport in report.Subreports)
{
RecursivelyRemapConnection(subreport, username, password, server, database);
}
}
}
}
问题是在我的开发环境中,它工作得很好,而在其他环境中我得到以下异常:
Log on failed. No error.
at CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocumentClass.VerifyDatabase()
at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.VerifyDatabase()
at CrystalDecisions.CrystalReports.Engine.ReportDocument.VerifyDatabase()
我通过执行以下操作验证了连接在我的开发环境中发生了变化:
- 正在创建我的数据源的副本
- 在设计器中,将数据源设置为复制的数据库
- 正在删除副本
- 在设计器中预览报表无法加载(如预期)
- 正在使用我的实用程序生成报告class
最后一步成功生成了报告,告诉我数据源正在更改,否则我会预期登录失败。
特别令人沮丧的是,非开发环境中的一些报告工作正常,而另一些报告却产生异常。所以我不明白为什么它对某些人有效,但对所有人无效。
更新
如果我将开发环境中的连接字符串更改为 Azure 或 On-Prem 中使用的连接字符串,它在我的开发环境中仍然有效。我真的不相信问题出在我的连接字符串上,但是此时我又不知道是什么导致了登录失败。
经过几天的调查,我终于找到了导致问题的原因。
失败的特定报告使用 MSOLEDBSQL
提供程序而不是 SQLOLEDB
。
为了解决这个问题,我:
- 在 Visual Studio
中打开了 Crystal 报告
- 右键单击报表
- 数据库 > 设置数据源位置
- 扩展了当前数据源的属性
- 双击提供商
- 将值从
MSOLEDBSQL
更改为 SQLOLEDB
- 重新输入登录凭据(即使它们在运行时被更改)
- 已保存报告
- 构建解决方案
- 重新发布项目
我们有几个环境:
- 发展
- 蔚蓝
- 本地
Crystal报表从SQL服务器拉取数据,但数据库因环境不同而不同。
项目中有一个名为 connectionStrings.config
的配置文件,我们用于网站的连接字符串存储在那里。文件内容如下所示:
<connectionStrings>
<add name="dataModel" connectionString="data source=...;initial catalog=...;user id=...;password=...;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
为了加载报告,我设置了以下 class:
public class CrystalReportUtil
{
static string ReportsDirectory = ConfigurationManager.AppSettings["ReportsDirectory"];
private static string ConnectionString = ConfigurationManager.ConnectionStrings["dataModel"].ConnectionString;
public static ReportDocument GetReport(string reportName)
{
var report = new ReportDocument();
var fileDirectory = $"{Utilities.GetProjectRoot()}/Reports";
if (System.Web.HttpContext.Current != null)
{
fileDirectory = System.Web.HttpContext.Current.Server.MapPath(ReportsDirectory);
}
string file = Path.Combine(fileDirectory, $"{reportName}.rpt");
if (!File.Exists(file))
{
throw new System.Exception($"Unable to find report file: {file}");
}
report.Load(file);
var builder = new SqlConnectionStringBuilder(ConnectionString);
var dataSource = builder.DataSource;
var user = builder.UserID;
var password = builder.Password;
var database = builder.InitialCatalog;
RecursivelyRemapConnection(report, user, password, dataSource, database);
report.VerifyDatabase();
return report;
}
private static void RecursivelyRemapConnection(ReportDocument report, string username, string password, string server, string database)
{
foreach (IConnectionInfo connection in report.DataSourceConnections)
{
connection.SetLogon(username, password);
connection.SetConnection(server, database, false);
}
report.SetDatabaseLogon(username, password);
foreach (Table table in report.Database.Tables)
{
table.LogOnInfo.ConnectionInfo.ServerName = server;
table.LogOnInfo.ConnectionInfo.DatabaseName = database;
table.LogOnInfo.ConnectionInfo.UserID = username;
table.LogOnInfo.ConnectionInfo.Password = password;
table.LogOnInfo.ConnectionInfo.IntegratedSecurity = false;
}
if (!report.IsSubreport)
{
foreach (ReportDocument subreport in report.Subreports)
{
RecursivelyRemapConnection(subreport, username, password, server, database);
}
}
}
}
问题是在我的开发环境中,它工作得很好,而在其他环境中我得到以下异常:
Log on failed. No error.
at CrystalDecisions.ReportAppServer.ClientDoc.ReportClientDocumentClass.VerifyDatabase()
at CrystalDecisions.ReportAppServer.ReportClientDocumentWrapper.VerifyDatabase()
at CrystalDecisions.CrystalReports.Engine.ReportDocument.VerifyDatabase()
我通过执行以下操作验证了连接在我的开发环境中发生了变化:
- 正在创建我的数据源的副本
- 在设计器中,将数据源设置为复制的数据库
- 正在删除副本
- 在设计器中预览报表无法加载(如预期)
- 正在使用我的实用程序生成报告class
最后一步成功生成了报告,告诉我数据源正在更改,否则我会预期登录失败。
特别令人沮丧的是,非开发环境中的一些报告工作正常,而另一些报告却产生异常。所以我不明白为什么它对某些人有效,但对所有人无效。
更新
如果我将开发环境中的连接字符串更改为 Azure 或 On-Prem 中使用的连接字符串,它在我的开发环境中仍然有效。我真的不相信问题出在我的连接字符串上,但是此时我又不知道是什么导致了登录失败。
经过几天的调查,我终于找到了导致问题的原因。
失败的特定报告使用 MSOLEDBSQL
提供程序而不是 SQLOLEDB
。
为了解决这个问题,我:
- 在 Visual Studio 中打开了 Crystal 报告
- 右键单击报表
- 数据库 > 设置数据源位置
- 扩展了当前数据源的属性
- 双击提供商
- 将值从
MSOLEDBSQL
更改为SQLOLEDB
- 重新输入登录凭据(即使它们在运行时被更改)
- 已保存报告
- 构建解决方案
- 重新发布项目