如何在运行时更改Crystal Report的ODBC数据库连接?

10

我有一个使用Crystal Reports 2008制作的报表,需要部署到生产系统中,这意味着我需要能够在运行时更改数据库连接。数据库是PostgreSQL 8.3.0,我用于创建初始报表的连接是ODBC连接。

我已经找到了各种更改数据库连接的方式,包括以下方法:

reportDoc.Load(report);
reportDoc.DataSourceConnections[0].SetConnection("server", "database", "user", "pwd");
reportDoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, path);

然而,这总是会失败并显示以下错误信息:

无法打开连接。

我已通过使用pgAdmin III成功连接到数据库来验证连接参数,因此我知道连接参数是正确的。此外,如果我删除SetConnection(...)行,使代码如下所示:

reportDoc.Load(report);
reportDoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, path);

如果使用存储在报表中的连接参数,则该报表可以正常运行。这种方法是否不适用于ODBC连接?

如何在运行时更改Crystal Report的ODBC数据库连接?

6个回答

17

经过更深入的研究,我发现这个问题有两个部分的解决方案。

第一部分

如果您正在通过ODBC连接到PostgreSQL(截至本文撰写时,这是Crystal Reports从PostgreSQL获取数据的唯一方式),并且使用数据所有者,则可以使用以下代码:

reportDoc.Load(report);
reportDoc.DataSourceConnections[0].SetConnection("Driver={PostgreSQL ANSI};Server=myServer;Port=5432;", "myDatabase", "myUser", "myPassword");
reportDoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, path);
// Depending on your application you may have more than one data source connection that needs to be changed.

如果您作为拥有报告数据的用户连接,则此方法仅适用,因为不需要提供模式名称。

第二部分

如果您使用数据所有者以外的用户通过ODBC连接到PostgreSQL,则需要手动提供模式名称。可以使用以下代码实现。

reportDoc.Load(report);

ConnectionInfo connInfo = new ConnectionInfo();
connInfo.ServerName = "Driver={PostgreSQL ANSI};Server=myServer;Port=5432;";
connInfo.DatabaseName = "myDatabase";
connInfo.UserID = "myUser";
connInfo.Password = "myPassword";

TableLogOnInfo tableLogOnInfo = new TableLogOnInfo();
tableLogOnInfo.ConnectionInfo = connInfo;

foreach (Table table in reportDoc.Database.Tables)
{
    table.ApplyLogOnInfo(tableLogOnInfo);
    table.LogOnInfo.ConnectionInfo.ServerName = connInfo.ServerName;
    table.LogOnInfo.ConnectionInfo.DatabaseName = connInfo.DatabaseName;
    table.LogOnInfo.ConnectionInfo.UserID = connInfo.UserID;
    table.LogOnInfo.ConnectionInfo.Password = connInfo.Password;

    // Apply the schema name to the table's location
    table.Location = "mySchema." + table.Location;
}

reportDoc.ExportToDisk(CrystalDecisions.Shared.ExportFormatType.PortableDocFormat, path);

概述

在尝试从Crystal Reports连接到PostgreSQL数据库时,有两个关键信息需要注意。

  1. 必须在服务器名称属性中指定驱动程序、服务器和端口号。
  2. 如果以数据所有者之外的用户身份连接,则必须为您从中提取数据的每个表指定模式名称。

来源

使用了多个来源,但没有一个答案适用于我的具体情况,但它们引导了我正确的方向。这些来源如下所示。


1
谢谢,这帮助我摆脱了Crystal Reports的泥潭。 - Dan Diplo
@Dan 对Crystal报表的泥潭给予加1。 - Nathan Koop
@amateurprogrammer,如果您提供适当的mysql驱动程序/连接字符串,我不明白为什么这不起作用。 - Ryan Taylor

2

首先感谢您提供这个信息!!!

我正在使用MySQL/C#/Crystal Reports。在设置好ODBC/DSN之后,像这样简单的内容对我很有帮助。

using CrystalDecisions.CrystalReports.Engine;

using CrystalDecisions.Shared;

using MySql.Data.MySqlClient;

.
.
.

ConnectionInfo connInfo = new ConnectionInfo();

connInfo.ServerName = "Driver={MySQL ODBC 3.51 Driver};DSN=MyODBCDatasourceName";

TableLogOnInfo tableLogOnInfo = new TableLogOnInfo();

tableLogOnInfo.ConnectionInfo = connInfo;

// rpt is my Crystal Reports ReportDocument

// Apply the schema name to the table's location

foreach (Table table in rpt.Database.Tables)

{

    table.ApplyLogOnInfo(tableLogOnInfo);

    table.Location = table.Location;

}

2

更新Crystal Report文件中的ODBC。

我们正在使用ODBC与MSSQL,我们找不到如何在C#项目中更新Crystal文件中的ODBC。

通过这里提供的示例,我们能够找到更新MSSQL中ODBC的方法,它非常简单:

       Cursor.Current = Cursors.WaitCursor;

        CrystalDecisions.Windows.Forms.CrystalReportViewer CR_Viewer;
        CR_Viewer = new CrystalDecisions.Windows.Forms.CrystalReportViewer();
        this.Controls.Add(CR_Viewer);

        ConnectionInfo connInfo = new ConnectionInfo();
        connInfo.ServerName = "YOUR ODBC NAME"; 

        TableLogOnInfo tableLogOnInfo = new TableLogOnInfo();
        tableLogOnInfo.ConnectionInfo = connInfo;

         //THIS IS A CRYSTAL RPT FILE DIFINE AS A CLASS
        Facturation_Nord_Ouest.Reports.Facture_Français CrystalReportFr;


       CrystalReportFr = new Facturation_Nord_Ouest.Reports.Facture_Français();

            for (int i = 0; i < CrystalReportFr.Database.Tables.Count; i++)
            {
                CrystalReportFr.Database.Tables[i].ApplyLogOnInfo(tableLogOnInfo);
            }
            CR_Viewer.ReportSource = CrystalReportFr;

        CR_Viewer.ActiveViewIndex = 0;
        CR_Viewer.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
        CR_Viewer.Dock = System.Windows.Forms.DockStyle.Fill;
        CR_Viewer.Location = new System.Drawing.Point(0, 0);
        CR_Viewer.Size = new System.Drawing.Size(545, 379);
        CR_Viewer.TabIndex = 0;
        CR_Viewer.Name = "Invoice";
        CR_Viewer.Zoom(100);
        CR_Viewer.Show();

        Cursor.Current = Cursors.Default;

这样,crystal文件中的ODBC会自动更新。


这对我很有用,最重要的一行是 connInfo.ServerName = "YOUR ODBC NAME"; 感谢 patm。 - DeveloperChris

2

我刚刚经历了同样的磨难。

我将我的连接设置成这样(其中sDataSource等是包含信息的字符串)

    Dim myConnectionInfo As ConnectionInfo = New ConnectionInfo()
    myConnectionInfo.ServerName = sDataSource
    myConnectionInfo.DatabaseName = sInitialCatalog
    myConnectionInfo.UserID = sUserID
    myConnectionInfo.Password = sPassword

    Dim myTables As Tables = report.Database.Tables
    Dim myTableLogonInfo As TableLogOnInfo = New TableLogOnInfo()
    myTableLogonInfo.ConnectionInfo = myConnectionInfo
    For Each myTable As CrystalDecisions.CrystalReports.Engine.Table In myTables
        myTable.ApplyLogOnInfo(myTableLogonInfo)

        myTable.LogOnInfo.ConnectionInfo.DatabaseName = myTableLogonInfo.ConnectionInfo.DatabaseName
        myTable.LogOnInfo.ConnectionInfo.ServerName = myTableLogonInfo.ConnectionInfo.ServerName
        myTable.LogOnInfo.ConnectionInfo.UserID = myTableLogonInfo.ConnectionInfo.UserID
        myTable.LogOnInfo.ConnectionInfo.Password = myTableLogonInfo.ConnectionInfo.Password

    Next

这对我仍然失败,出现相同的“无法打开连接”错误消息。你使用的是哪个数据库? - Ryan Taylor
我不确定PostgreSQL是否有这个功能,但是您是否正在使用集成安全性?我了解(在SQL Server中)您无法从集成安全性切换到用户名/密码安全性。 - Nathan Koop
请确保您的测试机器(如果与开发机器不同)已安装适当的驱动程序。 - Nathan Koop
1
我没有使用集成安全。此外,我的测试是在我的开发机器上进行的,并且当我不在运行时修改连接时,报告将在我的开发机器上正确运行,因为我有适当的驱动程序。 - Ryan Taylor
感谢您提供的所有信息和快速响应。最终,我采取了不同的方法(代码更少)。由于我正在使用ODBC连接,而Crytsal Reports没有原生支持PostgreSQL,所以我最终需要在服务器名称中指定驱动程序和端口。 - Ryan Taylor

0
protected void Page_Load(object sender, EventArgs e)
        {
            try
            {

                ReportDocument cryRpt = new ReportDocument();
                TableLogOnInfos crtableLogoninfos = new TableLogOnInfos();
                TableLogOnInfo crtableLogoninfo = new TableLogOnInfo();
                ConnectionInfo crConnectionInfo = new ConnectionInfo();
                cryRpt.Load(@"D:\tem\WebAppReport\WebAppReport\CrystalReport1.rpt");
                crConnectionInfo.ServerName = "misserver";
                crConnectionInfo.DatabaseName = "testAccountability_data";
                crConnectionInfo.UserID = "RW";
                crConnectionInfo.Password = "RW";


                foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in cryRpt.Database.Tables)
                {
                    crtableLogoninfo = CrTable.LogOnInfo;
                    crtableLogoninfo.ConnectionInfo = crConnectionInfo;
                    CrTable.ApplyLogOnInfo(crtableLogoninfo);
                }

                CrystalReportViewer1.ReportSource = cryRpt;
                CrystalReportViewer1.RefreshReport();
            }
            catch
            {
            }






        }

0

这段代码适用于 Sql Server 2008 R2 的无 DSN 连接。

Dim myConnectionInfo As CrystalDecisions.Shared.ConnectionInfo = New CrystalDecisions.Shared.ConnectionInfo()

    myConnectionInfo.ServerName = "Driver={SQL Server Native Client 10.0};Server=P03\sqlrs1;"
    myConnectionInfo.DatabaseName = "RS1DB"
    myConnectionInfo.UserID = "user"
    myConnectionInfo.Password = "pwd"

    For Each myTable As CrystalDecisions.CrystalReports.Engine.Table In mboReportDocument.Database.Tables

        Dim myTableLogonInfo As TableLogOnInfo = myTable.LogOnInfo
        myTableLogonInfo.ConnectionInfo = myConnectionInfo
        myTable.ApplyLogOnInfo(myTableLogonInfo)

    Next

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接