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()

我通过执行以下操作验证了连接在我的开发环境中发生了变化:

  1. 正在创建我的数据源的副本
  2. 在设计器中,将数据源设置为复制的数据库
  3. 正在删除副本
  4. 在设计器中预览报表无法加载(如预期)
  5. 正在使用我的实用程序生成报告class

最后一步成功生成了报告,告诉我数据源正在更改,否则我会预期登录失败。

特别令人沮丧的是,非开发环境中的一些报告工作正常,而另一些报告却产生异常。所以我不明白为什么它对某些人有效,但对所有人无效。

更新

如果我将开发环境中的连接字符串更改为 Azure 或 On-Prem 中使用的连接字符串,它在我的开发环境中仍然有效。我真的不相信问题出在我的连接字符串上,但是此时我又不知道是什么导致了登录失败。

经过几天的调查,我终于找到了导致问题的原因。

失败的特定报告使用 MSOLEDBSQL 提供程序而不是 SQLOLEDB

为了解决这个问题,我:

  1. 在 Visual Studio
  2. 中打开了 Crystal 报告
  3. 右键单击报表
  4. 数据库 > 设置数据源位置
  5. 扩展了当前数据源的属性
  6. 双击提供商
  7. 将值从 MSOLEDBSQL 更改为 SQLOLEDB
  8. 重新输入登录凭据(即使它们在运行时被更改)
  9. 已保存报告
  10. 构建解决方案
  11. 重新发布项目