使用MySQL Connector/NET
26.2.4.1. 前言
26.2.4.2. 使用MySQL Connector/NET连接到MySQL
26.2.4.3. 与预处理语句一起使用MySQL Connector/NET
26.2.4.4. 用MySQL Connector/NET访问存储程序
26.2.4.5. 用Connector/NET处理BLOB数据
26.2.4.6. 与Crystal Reports一起使用MySQL Connector/NET
26.2.4.7. 在MySQL Connector/NET中处理日期和时间信息
26.2.4.1. 前言
在本节中,介绍的Connector/NET的一些常用方式,包括BLOB处理,日期处理,以及与诸如Crystal Reports等常见工具一起使用Connector/NET的方法。
26.2.4.2. 使用MySQL Connector/NET连接到MySQL
26.2.4.2.1. 前言
26.2.4.2.2. 创建连接字符串
26.2.4.2.3. 打开连接
26.2.4.2.4. 处理连接错误
26.2.4.2.1. 前言
.NET应用程序和MySQL服务器之间的所有交互均是通过MySqlConnection对象传送的。在应用程序能够与服务器进行交互之前,必须获取、配置、并打开MySqlConnection对象。
即使在使用MySqlHelper类时,MySqlConnection对象也会被Helper类创建。
在本节中,介绍了使用MySqlConnection对象连接到MySQL的方法。
26.2.4.2.2. 创建连接字符串
MySqlConnection对象是使用连接字符串配置的。1个连接字符串包含服务器键/值对,由分号隔开。每个键/值对由等号连接。
下面给出了1个简单的连接字符串示例:
Server=127.0.0.1;Uid=root;Pwd=12345;Database=test; 在本例中,对MySqlConnection对象进行了配置,使用用户名“root”和密码“12345”与位于127.0.0.1的MySQL服务器相连。所有语句的默认数据库为测试数据库。
典型的选项如下(关于选项的完整清单,请参见API文档):
· Server:将要连接的MySQL实例的名称或网络地址。默认为本地主机。别名包括Host, Data Source, DataSource, Address, Addr和Network Address。
· Uid:连接时使用的MySQL用户账户。别名包括User Id, Username和User name。
· Pwd:MySQL账户的密码。也可以使用别名密码。
· Database:所有语句作用于的默认数据库。默认为mysql。也可以使用别名Initial Catalog。
· Port:MySQL用于监听连接的端口。默认为3306。将该值指定为“-1”将使用命名管道连接。
26.2.4.2.3. 打开连接
一旦创建了连接字符串,可使用它打开与MySQL服务器的连接。
下述代码用于创建MySqlConnection对象,指定连接字符串,并打开连接。
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;
myConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
conn = new MySql.Data.MySqlClient.MySqlConnection();
conn.ConnectionString = myConnectionString;
conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
}
你也可以将连接字符串传递给MySqlConnection类的构造函数:
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;
myConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString);
conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message);
}
一旦打开了连接,其他MySQL Connector/NET类也能使用该连接与MySQL服务器进行通信。
26.2.4.2.4. 处理连接错误
由于与外部服务器的连接不可预测,应为你的.NET应用程序添加错误处理功能,这点很重要。出现连接错误时,MySqlConnection类将返回1个MySqlException对象。该对象有两个在处理错误时十分有用的属性:
· Message:描述当前异常的消息。
· Number:MySQL错误编号。
处理错误时,可根据错误编号了解应用程序的响应。进行连接时最常见的两个错误编号如下:
· 0: 无法连接到服务器。
· 1045: 无效的用户名和/或密码。
在下面的代码中,介绍了根据实际错误改编应用程序的方法:
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
string myConnectionString;
myConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
conn = new MySql.Data.MySqlClient.MySqlConnection(myConnectionString);
conn.Open();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
switch (ex.Number)
{
case 0:
MessageBox.Show(”Cannot connect to server. Contact administrator”);
case 1045:
MessageBox.Show(”Invalid username/password, please try again”);
}
}
26.2.4.3. 与预处理语句一起使用MySQL Connector/NET
26.2.4.3.1. 前言
26.2.4.3.2. 在MySQL Connector/NET中准备语句
26.2.4.3.1. 前言
从MySQL 4.1开始,能够与MySQL Connector/NET一起使用预处理语句。使用预处理语句能够现住改善多次执行的查询的性能。
对于多次执行的语句,预处理执行的速度快于直接执行,这是因为只需进行1次解析操作。在直接执行的情况下,每次执行时均将进行解析操作。预处理执行还能降低网络通信量,这是因为对于预处理语句的每次执行,仅需发送用于参数的数据。
预处理语句的另一优点是,它能使用二进制协议,这使得客户端和服务器间的数据传输更有效率。
26.2.4.3.2. 在MySQL Connector/NET中准备语句
为了准备好语句,需创建1个命令对象,并为查询设置.CommandText属性。
输入语句后,调用MySqlCommand对象的.Prepare方法。完成语句的准备后,为查询中的每个元素添加参数。
输入查询并输入参数后,使用.ExecuteNonQuery()、.ExecuteScalar()、或.ExecuteReader方法执行语句。
对于后续的执行操作,仅需更改参数值并再次调用执行方法,无需设置.CommandText属性或重新定义参数。
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;MySql.Data.MySqlClient.MySqlCommand cmd; conn = new MySql.Data.MySqlClient.MySqlConnection();cmd = new MySql.Data.MySqlClient.MySqlCommand(); conn.ConnectionString = strConnection; try{ conn.Open(); cmd.Connection = conn; cmd.CommandText = “INSERT INTO myTable VALUES(NULL, ?number, ?text)”; cmd.Prepare(); cmd.Parameters.Add(”?number”, 1); cmd.Parameters.Add(”?text”, “One”); for (int i=1; i <= 1000; i++) { cmd.Parameters["?number"].Value = i; cmd.Parameters["?text"].Value = “A string value”; cmd.ExecuteNonQuery(); }}catch (MySql.Data.MySqlClient.MySqlException ex){ MessageBox.Show(”Error ” + ex.Number + ” has occurred: ” + ex.Message, “Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);}
26.2.4.4. 用MySQL Connector/NET访问存储程序
26.2.4.4.1. 前言
26.2.4.4.2. 从MySQL Connector/NET创建存储程序
26.2.4.4.3. 从MySQL Connector/NET调用存储程序
26.2.4.4.1. 前言
随着MySQL版本5的发布,MySQL服务器目前支持存储程序,它采用了SQL 2003存储程序的语法。
存储程序指的是能够保存在服务器上的一组SQL语句。 一旦完成了该操作,客户端无需再次发出单独语句,而仅需引用存储程序取而代之。
在下述情况下,存储程序尤其有用:
· 多个客户端应用程序是采用不同语言编写的或工作在不同平台上,但需执行相同的数据库操作。
· 安全性极其重要时。例如,对于所有共同操作,银行采用了存储程序。这样,就能提供一致且安全的环境,而且这类存储程序能够保证每次操作均具有恰当登录。在这类设置下,应用程序和用户无法直接访问数据库表,但能执行特定的存储程序。
MySQL Connector/NET支持通过MySqlCommand对象的存储程序调用。使用MySqlCommand.Parameters集,能够将数据传入和传出MySQL存储程序。
在本节中,未深度介绍创建存储程序方面的信息,要想了解这类信息,请参见MySQL参考手册的存储程序。
在MySQL Connector/NET安装的Samples目录下,可找到1个相应的示例,该示例演示了与MySQL Connector/NET一起使用存储程序的方法。
26.2.4.4.2. 从MySQL Connector/NET创建存储程序
可使用多种工具创建MySQL中的存储程序。首先,可使用mysql命令行客户端创建存储程序。其次,可使用MySQL Query Browser GUI客户端创建存储程序。最后,可使用MySqlCommand对象的.ExecuteNonQuery方法创建存储程序。
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = “CREATE PROCEDURE add_emp(” +
“IN fname VARCHAR(20), IN lname VARCHAR(20), IN bday DATETIME, OUT empno INT) ” +
“BEGIN INSERT INTO emp(first_name, last_name, birthdate) ” +
“VALUES(fname, lname, DATE(bday)); SET empno = LAST_INSERT_ID(); END”;
cmd.ExecuteNonQuery();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(”Error ” + ex.Number + ” has occurred: ” + ex.Message,
“Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
请注意,不同于命令行和GUI客户端,在MySQL Connector/NET中创建存储程序时不需要指定特殊的定界符。
26.2.4.4.3. 从MySQL Connector/NET调用存储程序
要想使用MySQL Connector/NET来调用存储程序,应创建1个MySqlCommand对象,并将存储程序名作为.CommandText属性传递。将.CommandType属性设置为CommandType.StoredProcedure。
命名了存储程序后,为存储程序中的每个参数创建1个MySqlCommand参数。用参数名和包含值的对象定义IN参数,用参数名和预计将返回的数据类型定义OUT参数。对于所有参数,均需定义参数方向。
定义完参数后,使用MySqlCommand.ExecuteNonQuery()方法调用存储程序。
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = “add_emp”;
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(”?lname”, “Jones”);
cmd.Parameters(”?lname”).Direction = ParameterDirection.Input;
cmd.Parameters.Add(”?fname”, “Tom”);
cmd.Parameters(”?fname”).Direction = ParameterDirection.Input;
cmd.Parameters.Add(”?bday”, DateTime.Parse(”12/13/1977 2:17:36 PM”));
cmd.Parameters(”?bday”).Direction = ParameterDirection.Input;
cmd.Parameters.Add(”?empno”, MySqlDbType.Int32);
cmd.Parameters(”?empno”).Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
MessageBox.Show(cmd.Parameters(”?empno”).Value);
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(”Error ” + ex.Number + ” has occurred: ” + ex.Message,
“Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
一旦调用了存储程序,可使用MySqlConnector.Parameters集的.Value属性检索输出参数的值。
26.2.4.5. 用Connector/NET处理BLOB数据
26.2.4.5.1. 前言
26.2.4.5.2. 准备MySQL服务器
26.2.4.5.3. 将文件写入数据库
26.2.4.5.4. 将BLOB从数据库读取到磁盘上的文件
26.2.4.5.1. 前言
MySQL的1种用途是在BLOB列中保存二进制数据。MySQL支持4种不同的BLOB数据类型:TINYBLOB, BLOB, MEDIUMBLOB和LONGBLOB。
可使用Connector/NET访问保存在BLOB列中的数据,并能使用客户端代码对这类数据进行操作。使用Connector/NET和BLOB数据时,无特殊要求。
在本节中,给出了数个简单的代码示例,在MySQL Connector/NET安装的Samples目录下,可找到1个完整的示例应用程序。
26.2.4.5.2. 准备MySQL服务器
与BLOB数据一起使用MySQL的第1步是配置服务器。首先,让我们从创建要访问的表开始。在我的文件表中,通常有4列:1个具有恰当大小的AUTO_INCREMENT列(UNSIGNED SMALLINT),用于保存识别文件的主键;1个VARCHAR列,用于保存文件名;1个UNSIGNED MEDIUMINT列,用于保存文件的大小;以及1个用于保存文件本身的MEDIUMBLOB列。对于本例,我将使用下述表定义:
CREATE TABLE file(file_id SMALLINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,file_name VARCHAR(64) NOT NULL,file_size MEDIUMINT UNSIGNED NOT NULL,file MEDIUMBLOB NOT NULL);完成表的创建后,或许需要更改max_allowed_packet系统变量。该变量决定了能够发送给MySQL服务器的信息包(即单个行)大小。默认情况下,服务器能够接受来自客户端应用程序的信息包最大为1MB。如果不打算超过1MB,情况良好。如果打算在文件传输中超出1MB,必须增加该数值。
可以使用“MySQL系统管理员的启动变量”屏幕更改max_allowed_packet选项。在“联网”选项卡的“内存”部分,恰当调整“允许的最大值”选项。完成值的调整后,点击“应用更改”按钮,并使用“MySQL管理员”的“服务控制”屏幕重新启动服务器。也可以在my.cnf文件中直接调整该值(添加1行,max_allowed_packet=xxM),或在MySQL中使用SET max_allowed_packet=xxM。
设置max_allowed_packet时应保守些,这是因为传输BLOB数据需要一段时间。恰当地设置该值,使之与预期使用相符,并在必要时增大该值。
26.2.4.5.3. 将文件写入数据库
要想将文件写入数据库,需要将文件转换为字节数组,然后将字节数组用作INSERT查询的参数。
在下述代码中,使用FileStream对象打开了1个文件,将其读入至字节数组,然后将其插入到文件表中:
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
string SQL;
UInt32 FileSize;
byte[] rawData;
FileStream fs;
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
fs = new FileStream(@”c:/image.png”, FileMode.Open, FileAccess.Read);
FileSize = fs.Length;
rawData = new byte[FileSize];
fs.Read(rawData, 0, FileSize);
fs.Close();
conn.Open();
SQL = “INSERT INTO file VALUES(NULL, ?FileName, ?FileSize, ?File)”;
cmd.Connection = conn;
cmd.CommandText = SQL;
cmd.Parameters.Add(”?FileName”, strFileName);
cmd.Parameters.Add(”?FileSize”, FileSize);
cmd.Parameters.Add(”?File”, rawData);
cmd.ExecuteNonQuery();
MessageBox.Show(”File Inserted into database successfully!”,
“Success!”, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(”Error ” + ex.Number + ” has occurred: ” + ex.Message,
“Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
FileStream对象的“Read”方法可用于将文件加载到字节数组中,该字节数组的大小是根据FileStream对象的“Length”属性确定的。
将字节数组指定为MySqlCommand对象的参数后,调用ExecuteNonQuery方法,并将BLOB插入到文件表中。
26.2.4.5.4. 将BLOB从数据库读取到磁盘上的文件
一旦将文件加载到了文件表中,就能使用MySqlDataReader类来检索它。
在下述代码中,从文件表提取了1行,然后将数据装载到要写入至磁盘的FileStream对象。
[C#]
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataReader myData;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
string SQL;
UInt32 FileSize;
byte[] rawData;
FileStream fs;
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
SQL = “SELECT file_name, file_size, file FROM file”;
try
{
conn.Open();
cmd.Connection = conn;
cmd.CommandText = SQL;
myData = cmd.ExecuteReader();
if (! myData.HasRows)
throw new Exception(”There are no BLOBs to save”);
myData.Read();
FileSize = myData.GetUInt32(myData.GetOrdinal(”file_size”));
rawData = new byte[FileSize];
myData.GetBytes(myData.GetOrdinal(”file”), 0, rawData, 0, FileSize);
fs = new FileStream(@”C:/newfile.png”, FileMode.OpenOrCreate, FileAccess.Write);
fs.Write(rawData, 0, FileSize);
fs.Close();
MessageBox.Show(”File successfully written to disk!”,
“Success!”, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
myData.Close();
conn.Close();
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(”Error ” + ex.Number + ” has occurred: ” + ex.Message,
“Error”, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
连接后,文件表的内容将被加载到MySqlDataReader对象中。使用MySqlDataReader的GetBytes方法将BLOB加载到字节数组,然后使用FileStream对象将字节数据写入磁盘。
MySqlDataReader的GetOrdinal方法可用于确定命名列的整数索引。如果SELECT查询的列顺序发生变化,使用GetOrdinal方法能够防止错误。
26.2.4.6. 与Crystal Reports一起使用MySQL Connector/NET
26.2.4.6.1. 前言
26.2.4.6.2. 创建数据源
26.2.4.6.3. 创建报告
26.2.4.6.4. 显示报告
26.2.4.6.1. 前言
Crystal Reports是Windows应用程序开发人员用于通报文档生成的常用工具。在本节中,介绍了Crystal Reports XI与MySQL和Connector/NET一起使用的方法。
在MySQL Connector/NET安装的Samples目录的CrystalDemo子目录下,可找到完整的示例应用程序。
26.2.4.6.2. 创建数据源
在Crystal Reports中创建报告时,在设计报告时,有两个用于访问MySQL数据的选项。
第1个选项是,设计报告时,使用Connector/ODBC作为ADO数据源。你能够浏览数据库,并使用拖放式操作选择表和字段以创建报告。该方法的缺点是,必须在应用程序中执行额外操作以生成与报告预期的数据集匹配的数据集。
第2个选项是在VB.NET中创建数据集,并将其保存为XML格式。随后,该XML文件可被用于设计报告。在应用程序中显示报告时,它的表现相当良好,但设计时的通用性较差,这是因为在创建数据集时,必须选择所有的相关列。如果忘记选择了某一列,在能够将列添加到报告前,必须重新创建数据集。
使用下述代码,可根据查询操作创建数据集,并将其写入磁盘。
[C#]
DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
cmd.CommandText = “SELECT city.name AS cityName, city.population AS CityPopulation, ” +
“country.name, country.population, country.continent ” +
“FROM country, city ORDER BY country.continent, country.name”;
cmd.Connection = conn;
myAdapter.SelectCommand = cmd;
myAdapter.Fill(myData);
myData.WriteXml(@”C:/dataset.xml”, XmlWriteMode.WriteSchema);
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message, “Report could not be created”,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
设计报告时,可将该代码生成的XML文件用作ADO.NET XML数据源。
如果你选择使用Connector/ODBC来设计报告,可从dev.mysql.com下载它。
26.2.4.6.3. 创建报告
对于大多数应用目的,标准的报告向导应能帮助你完成报告的最初创建。要想启动向导,打开Crystal Reports并从“文件”菜单选择“New > Standard Report”选项。
向导首先要求你提供数据源。如果你正使用Connector/ODBC作为数据源,选择数据源时,请使用OLE DB (ADO)树的“用于ODBC的OLEDB provider”选项,,而不是来自ODBC (RDO)的对应选项。如果你使用的是已保存的数据集,请选择ADO.NET (XML)选项,并浏览你保存的数据集。
在报告的创建过程中,剩余部分将由向导自动完成。
创建完报告后,选择“文件”菜单中的“Report Options…”菜单项。取消对“Save Data With Report”(与报告一起保存数据)选项的选择。这样,就能防止保存的数据干扰应用程序中的数据加载操作。
26.2.4.6.4. 显示报告
要想显示报告,首先用报告所需的数据填充数据集,然后加载报告,并将其与绑定到数据集。最后,将报告传递给crViewer控制,以便向用户显示它。
在显示报告的项目中,需要下述引用:
· CrytalDecisions.CrystalReports.Engine
· CrystalDecisions.ReportSource
· CrystalDecisions.Shared
· CrystalDecisions.Windows.Forms
在下述代码中,假定你使用数据集(用创建数据源中给出的代码保存的数据集)创建了报告,并在名为“myViewer”的表单上有1个crViewer控件。
[C#]
using CrystalDecisions.CrystalReports.Engine;
using System.Data;
using MySql.Data.MySqlClient;
ReportDocument myReport = new ReportDocument();
DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
cmd.CommandText = “SELECT city.name AS cityName, city.population AS CityPopulation, ” +
“country.name, country.population, country.continent ” +
“FROM country, city ORDER BY country.continent, country.name”;
cmd.Connection = conn;
myAdapter.SelectCommand = cmd;
myAdapter.Fill(myData);
myReport.Load(@”./world_report.rpt”);
myReport.SetDataSource(myData);
myViewer.ReportSource = myReport;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message, “Report could not be created”,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
使用相同的查询(用于生成前面保存的数据集),可生成新的数据集。一旦填充了数据集,可使用ReportDocument加载报告文件,并将其与数据集绑定在一起。ReportDocument是作为crViewer的ReportSource而传递的。
使用Connector/ODBC从单个表创建报告时,采用了相同的方法。数据集替换报告中使用的表,并恰当显示报告。
如果报告是使用Connector/ODBC从多个表创建的,在我们的应用程序中必须创建具有多个表的数据集。这样,就能用数据集中的报告替换报告数据源中的各个表。
在我们的MySqlCommand对象中提供多条SELECT语句,通过该方式,用多个表填充数据集。这些SELECT语句基于SQL查询,如数据库菜单“Show SQL Query”选项中的“Crystal Reports”中显示的那样。假定有下述查询:
SELECT `country`.`Name`, `country`.`Continent`, `country`.`Population`, `city`.`Name`, `city`.`Population`FROM `world`.`country` `country` LEFT OUTER JOIN `world`.`city` `city` ON `country`.`Code`=`city`.`CountryCode`ORDER BY `country`.`Continent`, `country`.`Name`, `city`.`Name`该查询将被转换为两条SELECT查询,并以下述代码显示:
[C#]
using CrystalDecisions.CrystalReports.Engine;
using System.Data;
using MySql.Data.MySqlClient;
ReportDocument myReport = new ReportDocument();
DataSet myData = new DataSet();
MySql.Data.MySqlClient.MySqlConnection conn;
MySql.Data.MySqlClient.MySqlCommand cmd;
MySql.Data.MySqlClient.MySqlDataAdapter myAdapter;
conn = new MySql.Data.MySqlClient.MySqlConnection();
cmd = new MySql.Data.MySqlClient.MySqlCommand();
myAdapter = new MySql.Data.MySqlClient.MySqlDataAdapter();
conn.ConnectionString = “server=127.0.0.1;uid=root;” +
“pwd=12345;database=test;”;
try
{
cmd.CommandText = “SELECT name, population, countrycode FROM city ORDER ” +
“BY countrycode, name; SELECT name, population, code, continent FROM ” +
“country ORDER BY continent, name”;
cmd.Connection = conn;
myAdapter.SelectCommand = cmd;
myAdapter.Fill(myData);
myReport.Load(@”./world_report.rpt”);
myReport.Database.Tables(0).SetDataSource(myData.Tables(0));
myReport.Database.Tables(1).SetDataSource(myData.Tables(1));
myViewer.ReportSource = myReport;
}
catch (MySql.Data.MySqlClient.MySqlException ex)
{
MessageBox.Show(ex.Message, “Report could not be created”,
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
应将SELECT语句按字母顺序排列,这点很重要,原因在于,这是报告希望其源表所具有的顺序。对于报告中的每个表,均需要一条SetDataSource语句。
该方法会导致性能问题,这是因为Crystal Reports必须在客户端一侧将表绑定在一起,与使用以前保存的数据集相比,速度较慢。
26.2.4.7. 在MySQL Connector/NET中处理日期和时间信息
26.2.4.7.1. 前言
26.2.4.7.2. 使用无效日期时的问题
26.2.4.7.3. 限制无效日期
26.2.4.7.4. 处理无效日期
26.2.4.7.5. 处理NULL日期
26.2.4.7.1. 前言
MySQL和.NET语言处理日期和时间信息的方式是不同的,MySQL允许使用无法由.NET数据类型表示的日期,如“0000-00-00 00:00:00”。如果处理步当,该差异会导致问题。
在本节中,介绍了使用MySQL Connector/NET时恰当处理日期和时间信息的方法。
26.2.4.7.2. 使用无效日期时的问题
对于使用无效日期的开发人员来说,数据处理方面的差异会导致问题。无效的MySQL日期无法被加载到.NET DateTime对象中,包括NULL日期。
由于该原因,不能用MySqlDataAdapter类的Fill方法填充.NET DataSet对象,这是因为无效日期会导致System.ArgumentOutOfRangeException异常。
26.2.4.7.3. 限制无效日期
对日期问题的最佳解决方案是,限制用户输入无效日期。这即可在客户端上进行,也可在服务器端进行。
在客户端上限制无效日期十分简单,即总使用.NET DateTime类来处理日期。DateTime类仅允许有效日期,从而确保了数据库中的值也是有效的。该方法的缺点是,在使用.NET和非.NET代码操作数据库的混合环境下不能使用它,这是因为各应用程序必须执行自己的日期验证。
MySQL 5.0.2和更高版本的用户可使用新的传统SQL模式来限制无效日期值。关于使用传统SQL模式的更多信息,请参见http://dev.mysql.com/doc/mysql/en/server-sql-mode.html。
26.2.4.7.4. 处理无效日期
强烈建议在你的.NET应用程序中应避免使用无效日期,尽管如此,也能tongguo MySqlDateTime数据类型使用无效日期。
MySqlDateTime数据类型支持MySQL服务器支持的相同日期值。MySQL Connector/NET的默认行为是,对有效的日期值返回1个.NET DateTime对象,对无效日期值返回错误。可以更改该默认方式,使MySQL Connector/NET为无效日期返回MySqlDateTime对象。
要想使MySQL Connector/NET为无效日期返回MySqlDateTime对象,可在连接字符串中添加下行:
Allow Zero Datetime=True 请注意,使用MySqlDateTime类仍会产生问题。下面介绍了一些已知问题:
1. 无效日期的数据绑定仍会导致错误(零日期0000-00-00看上去不存在该问题)。
2. ToString方法返回按标准MySQL格式进行格式处理的日期(例如,2005-02-23 08:50:25)。这与.NET DateTime类的ToString行为不同。
3. MySqlDateTime类支持NULL日期,但.NET DateTime类不支持NULL日期。如果未首先检查NULL,在试图将MySQLDateTime转换为DateTime时,会导致错误。
由于存在上述已知事宜,最佳建议仍是,在你的应用程序中仅使用有效日期。
26.2.4.7.5. 处理NULL日期
.NET DateTime数据类型不能处理NULL值。同样,在查询中为DateTime变量赋值时,必须首先检查值是否是NULL。
使用MySqlDataReader时,在赋值前,应使用.IsDBNull方法检查值是否为NULL:
[C#]
if (! myReader.IsDBNull(myReader.GetOrdinal(”mytime”)))
myTime = myReader.GetDateTime(myReader.GetOrdinal(”mytime”));
else
myTime = DateTime.MinValue;
NULL值能够在数据集中使用,也能将其绑定以构成控件,无需特殊处理。