将 Crystal Report 与 Oracle 和参数化查询结合使用(将 SQL 查询参数传递给 Crystal Reports)






4.38/5 (13投票s)
在 .NET Windows 应用程序中使用 Crystal Report 和参数化查询(C#.NET Windows 应用程序)。将 SQL 查询参数传递给 Crystal Reports
引言
本文介绍如何在 .NET Windows 应用程序中使用 Crystal Report,并结合参数化查询以及使用 `dataset` 作为 Oracle 数据库。我在网上搜索了关于 Crystal Report 与 Oracle 参数化查询的文章,但没有找到一篇好文章,所以我在这里分享我的文章。
本文主要有三个要点:
- 带参数化查询的 Crystal Report
- 使用 Oracle 视图,因为在这种情况下存储过程无法胜任,原因在于 Oracle 存储过程不像 SQL Server 存储过程那样返回多行(记录集)。
- 使用 `DataSet`
因此,我在此项目中使用 Oracle 视图来绑定 Crystal Report 和 Dataset。然后,我像往常一样在视图上编写参数化查询,就像在数据库表上一样。所以这个项目将很好地说明如何将 Crystal Report 与 Oracle 结合使用。有很多方法可以做到这一点,我们甚至可以创建 Oracle 包,它们可以像 SQL Server 存储过程一样返回多条记录。但我发现这种方式简单快捷。
背景
本文不需要任何特殊的背景知识。任何初学者或中级开发者都能理解这段代码。如果你对数据库视图有基本了解会更好。
Using the Code
我为此项目创建了 2 个示例表和一个视图。表和视图的脚本如下,并附带了一些示例 `insert` 语句以提供示例数据。
create table tbl_project
(
PROJECT_ID NUMBER(4),
PROJECT_NAME VARCHAR2(150),
GROUP_CODE NUMBER(2)
)
create table tbl_project_group
(
GROUP_CODE NUMBER(2),
GROUP_NAME VARCHAR2(100)
);
create view view_project as
select a.PROJECT_NAME "PROJECT_NAME",b.GROUP_NAME "GROUP_NAME",
a.GROUP_CODE "GROUP_CODE"
from tbl_project a,tbl_project_group b where
a.GROUP_CODE=b.GROUP_CODE;
insert into tbl_project values(1,'CrystalReportWithOracle',1);
insert into tbl_project values(2,'Ajax Application',2);
insert into tbl_project_group values(1,'windows application');
insert into tbl_project_group values(2,'Web application');
步骤 1
首先,在 Microsoft Visual Studio 2005 中创建一个名为 `CrystalReportWithOracle` 的项目。然后,像下面一样添加一个 Crystal Report。
第二步
然后,从可用数据源中选择 OLEDB(ADO),如下所示:
然后,选择 Oracle Provider for OLEDB 作为提供程序,如下图所示:
然后,根据你的 Oracle 配置提供必要的数据库登录信息。
步骤 3
然后,从可用数据源中,将之前创建的视图添加到选定的表 `Container` 中,并添加你将在报表中显示的字段,如下所示:
步骤 4
现在,向你的项目中添加一个空的 `DataSet`。
然后,从工具箱向你的窗体添加一个 Crystal Report Viewer 控件。
为了实现数据库连接,这里有一个类文件 `DLApplication.cs`。在这里,你可以根据你的 Oracle 配置更改连接字符串。如果你自己在窗体中创建连接,可以忽略此文件。
有一个组合框 (Combo Box),用户可以在其中选择他们想要的项目类型,以便应用程序根据用户的选择生成动态报表。填充组合框的代码如下:
String Query = "Select GROUP_CODE,GROUP_NAME from tbl_project_group order by GROUP_CODE ASC";
DLApplication oDl = new DLApplication();
OracleConnection Conn = oDl.GetCon();
DataView dv = oDl.getDataView(Query, Conn);
cmb_type.DataSource = dv;
cmb_type.ValueMember = "GROUP_CODE";
cmb_type.DisplayMember = "GROUP_NAME";
cmb_type.SelectedIndex = -1;
在上面的代码中,调用了带有所需参数的 `getDataView()` 函数。该函数位于 `DLApplication` 类中。
绑定 Crystal Report 的主函数如下,每当用户在组合框中更改选择时,就会为选定的组合框值生成新报表。
//
private void cmb_type_SelectedIndexChanged(object sender, EventArgs e)
{
if (Convert.ToInt32(cmb_type.SelectedIndex) == -1 ||
(Convert.ToString(cmb_type.SelectedValue) == "System.Data.DataRowView"))
{
return;
}
CrystalReport1 objRpt;
objRpt = new CrystalReport1();
String ConnStr = "SERVER=newsdb;USER ID=ppms;PWD=ppms";
OracleConnection myConnection = new OracleConnection(ConnStr);
// Here I am writing my query over the view
// we cannot write query directly over the tables because it will be a
// join query and we will not be able to fill our adapter easily.
string Query1 = "select PROJECT_NAME,GROUP_NAME from view_project
where GROUP_CODE=" + cmb_type.SelectedValue;
OracleDataAdapter adapter = new OracleDataAdapter(Query1, ConnStr);
DataSet1 Ds = new DataSet1();
adapter.Fill(Ds, "view_project");
if (Ds.Tables[0].Rows.Count == 0)
{
MessageBox.Show("No data Found", "Project Tracker Suite");
return;
}
objRpt.SetDataSource(Ds);
CrystalDecisions.CrystalReports.Engine.TextObject root;
root = (CrystalDecisions.CrystalReports.Engine.TextObject)
objRpt.ReportDefinition.ReportObjects["txtHeader"];
root.Text = "Sample Report With Parameter!!";
crystalReportViewer1.ReportSource = objRpt;
}
}
//
`DLApplication.cs` 文件包含返回 Oracle Data View、Oracle Data Reader 等的函数。你可以查看该类文件。
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.OracleClient;
namespace CrystalReportWithOracle
{
public class DLApplication
{
private const String My_name = " DLApplication : ";
private static String m_sConStr = "SERVER=yourdB;USER ID=user1;PWD=pass";
private int userId;
public int propertyUserId
{
get
{
return userId;
}
set
{
userId = value;
}
}
public OracleConnection GetCon()
{
try
{
OracleConnection sqlcon = new OracleConnection(m_sConStr);
return sqlcon;
}
catch (Exception ex)
{
throw new System.ApplicationException(My_name + " GetCon: " + ex.Message);
}
}
public OracleDataReader GetSqlReader(String Sql, ref OracleConnection con)
{
try
{
OracleCommand objOraCmd = new OracleCommand();
OracleDataReader objOraDrRead;
objOraCmd.Connection = con;
objOraCmd.CommandType = CommandType.Text;
objOraCmd.CommandText = Sql;
if (con.State != ConnectionState.Open) con.Open();
objOraDrRead = objOraCmd.ExecuteReader(CommandBehavior.CloseConnection);
return objOraDrRead;
}
catch (Exception ex)
{
throw new System.ApplicationException(My_name + " GetSqlReader: " + ex.Message);
}
}
public void CloseCon(ref OracleConnection thisCon)
{
try
{
if (thisCon.State != ConnectionState.Closed)
thisCon.Close();
}
catch (Exception ex)
{
throw new System.ApplicationException(My_name + " CloseCon: " + ex.Message);
}
}
public void ExecNonQuery(String sQuery)
{
OracleConnection objCon = new OracleConnection(m_sConStr);
OracleCommand objCmd;
try
{
objCon.Open();
objCmd = objCon.CreateCommand();
objCmd.CommandText = sQuery;
objCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw new System.ApplicationException(My_name + " ExecNonQuery : " + ex.Message);
}
finally
{
if (objCon.State == ConnectionState.Open)
objCon.Close();
}
}
public DataView getDataView(String Query, OracleConnection Conn)
{
try
{
OracleDataAdapter oDa;
DataSet ds;
oDa = new OracleDataAdapter(Query, Conn);
ds = new DataSet();
oDa.Fill(ds);
if (Conn.State != ConnectionState.Closed)
Conn.Close();
return (ds.Tables[0].DefaultView);
}
catch (Exception ex)
{
throw new System.ApplicationException(My_name + " getDataView : " + ex.Message);
}
finally
{
if (Conn.State != ConnectionState.Closed)
Conn.Close();
}
}
}
}
关注点
Oracle 存储过程不返回多个记录,我们可以使用包代替,但在这里,我使用了视图,它更容易理解。
很快,我将发布关于以下主题的文章:
历史
- 我将更新这篇文章,以更清晰地阐述这个主题。