C# 将DataTable设置为数据源时请求数据库登录的报告

C# 将DataTable设置为数据源时请求数据库登录的报告,c#,login,datatable,crystal-reports,dsn,C#,Login,Datatable,Crystal Reports,Dsn,报表设计器使用ODBC(DSN)连接直接连接到数据库,在设计器中创建crystal报表。相同的报告通过DSN通过Winform(C#)应用程序执行,并提供数据库服务器、数据库、用户ID和密码 我需要对Crystal Report对象进行这样的更改。ReportDocument不应通过DSN直接连接到数据库。相反,我们将通过调用相应的存储过程和参数作为System.data.DataTable,通过服务带来数据。此DataTable对象应用于填充/生成报告 我确实分别从ReportDocument

报表设计器使用ODBC(DSN)连接直接连接到数据库,在设计器中创建crystal报表。相同的报告通过DSN通过Winform(C#)应用程序执行,并提供数据库服务器、数据库、用户ID和密码

我需要对Crystal Report对象进行这样的更改。ReportDocument不应通过DSN直接连接到数据库。相反,我们将通过调用相应的存储过程和参数作为
System.data.DataTable
,通过服务带来数据。此
DataTable
对象应用于填充/生成报告

我确实分别从
ReportDocument.DataBase.Tables[I].Location
ReportDocument.DataDefinition
对象获取存储过程和参数信息。在使用ReportDocument.DataBase.Tables[I].SetDataSource(DataTable)设置数据源后,它仍然要求数据库/服务器和用户凭据连接到服务器


我们能否实现该方案并使用内存中的表来填充报表,而不是通过ODBC直接连接到数据库?

您需要关注两件事:

  • 您正在连接的服务器和数据库名称与设计报表时使用的服务器和数据库名称相同
  • 您正在连接到不同的数据库或服务器
  • 场景1:相同的服务器和数据库名称

    在这种情况下,您需要使用
    SetDatabaseLogon
    方法提供凭据,如下所示

    'crDoc1 is your ReportDocument
    'dtDataTable is your DataTable
    
    'set database logon info
    crDoc1.SetDatabaseLogon("db_user_name", "db_password", "db_server_name_or_ip", "database_name");
    
    'set DataTable as DataSource
    crDoc1.SetDataSource(dtDataTable)
    
    场景2:不同的服务器或数据库名称

    在这种情况下,您需要使用
    ApplyLogOnInfo
    方法提供凭据

    ConnectionInfo crConInfo = new ConnectionInfo();
    TableLogOnInfo crTblLogonInfo = new TableLogOnInfo();
    
    crConInfo.ServerName = "db_server_name_or_ip";
    crConInfo.DatabaseName = "database_name";
    crConInfo.UserID = "db_user_name";
    crConInfo.Password = "db_password";  
    
    'crDoc1 is your ReportDocument
    'dtDataTable is your DataTable
    
    'Set DataSource to your DataTable
    crDoc1.SetDataSource(dtDataTable)
    
    'after setting the DataSource apply Logon credentials to each table in ReportDocument
    Tables CrTables = crDoc1.Database.Tables;
    foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in CrTables) {
        crTblLogonInfo = CrTable.LogOnInfo;
        crTblLogonInfo.ConnectionInfo = crConInfo;
        CrTable.ApplyLogOnInfo(crTblLogonInfo);
    }
    crDoc1.Refresh();
    CrystalReportViewer1.ReportSource = crDoc1;
    
    注意:如果您有任何子报表,则需要分别将
    SetDatabaseLogon
    和/或
    ApplyLogOnInfo
    应用于所有子报表及其表

    更新:
    将ApplyLogOnInfo应用于子报表

    foreach (ReportDocument srSubReport in crDoc1.Subreports) {
        foreach (CrystalDecisions.CrystalReports.Engine.Table CrTable in srSubReport.Database.Tables) {
            crTblLogonInfo = CrTable.LogOnInfo;
            crTblLogonInfo.ConnectionInfo = crConInfo;
            CrTable.ApplyLogOnInfo(crTblLogonInfo);
        }
    }
    

    当我的数据已经在DataTable中可用时,为什么我需要提供数据库连接信息?它的CR安全特性保护数据免受未经授权的访问。数据库凭据(如密码)不会保存到报告中。在设计crystal报表表结构时,使用当前数据库连接和logininfo将字段、字段类型和大小、关系等嵌入到报表中。当您指定自己的断开连接的数据(DataTables)时,新架构信息必须与现有架构信息匹配。您只需查看Crystal Report的SQL查询就可以有一个想法?因此,对于数据、数据库验证和安全性,您必须在每次加载CR时指定它。还必须指定断开连接的数据,例如DataTable存储表结构和data only。没有嵌入数据库、连接详细信息。