成功建立数据库连接后,可以通过数据库连接进行对数据库的操作。本章讲述对数据库的查询操作。有如下内容:

  命令Command对象

  从数据库获取单值

  用DataReader查询

从数据库中获取blob值

  使用DataAdapter填充DataSet

1.Command对象

  当建立与数据源的连接后,可以使用 Command 对象来执行命令并从数据源中返回结果。

  您可以使用 Command 构造函数来创建命令,该构造函数采用在数据源、Connection 对象和 Transaction 对象中执行的 SQL 语句的可选参数。

  也可以使用 Connection 的 CreateCommand 方法来创建用于特定 Connection 对象的命令。

  您可以使用 CommandText 属性来查询和修改 Command 对象的 SQL 语句。

  Command 对象公开了几个可用于执行所需操作的 Execute 方法。

    当以数据流的形式返回结果时,使用 ExecuteReader 可返回 DataReader 对象。

    使用 ExecuteScalar 可返回单个值。

    使用 ExecuteNonQuery 可执行不返回行的命令。

// 创建连接实例
DbConnection myConnection = new SqlConnection();
// 设置连接字符串
myConnection.ConnectionString = "user id=userName;password=pass;initial catalog=northwind;data source=mySQLServer;Connect Timeout=30";
// 打开连接
myConnection.Open();

// 创建命令
DbCommand selectCommand = myConnection.CreateCommand();
selectCommand.CommandText
= "select * from TestTableName";

2.从数据库获取单值

  通过Command的ExecuteScalar 方法可返回单个值(结果中第一条记录的第一个字段)

// 创建连接实例
DbConnection myConnection = new SqlConnection();
// 设置连接字符串
myConnection.ConnectionString = "user id=userName;password=pass;initial catalog=northwind;data source=mySQLServer;Connect Timeout=30";
// 打开连接
myConnection.Open();

// 创建命令
DbCommand selectCommand = myConnection.CreateCommand();
selectCommand.CommandText
= "select count(*) from TestTableName";
// 执行查询操作,返回单值
Int32 count = (Int32)selectCommand.ExecuteScalar();

3.用DataReader查询

  可以使用 ADO.NET DataReader 从数据库中检索只读、只进的数据流。因为每次在内存中始终只有一行,所以使用 DataReader 可提高应用程序的性能并减少系统开销。
  当创建 Command 对象的实例后,可调用 Command.ExecuteReader 从数据源中检索行,从而创建一个 DataReader。
  使用 DataReader 对象的 Read 方法可从查询结果中获取行。通过向 DataReader 传递列的名称或序号引用,可以访问返回行的每一列。不过,为了实现最佳性能,DataReader 提供了一系列方法,它们将使您能够访问其本机数据类型(GetDateTime、GetDouble、GetGuid、GetInt32 等)形式的列值。

// 创建命令
DbCommand selectCommand = myConnection.CreateCommand();
selectCommand.CommandText
= "select intTypeField,strTypeField from TestTableName";

// 返回查询结果
DbDataReader myReader = selectCommand.ExecuteReader();

while (myReader.Read())
Console.WriteLine(
"\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));
myReader.Close();

  每次使用完 DataReader 对象后都应调用 Close 方法。

  如果 Command 包含输出参数或返回值,那么在 DataReader 关闭之前,将无法访问这些输出参数或返回值。

  请注意,当 DataReader 打开时,该 DataReader 将以独占方式使用 Connection。在初始 DataReader 关闭之前,将无法对 Connection 执行任何命令(包括创建另一个 DataReader)。

  如果返回的是多个结果集,DataReader 会提供 NextResult 方法来按顺序循环访问这些结果集

// 创建命令
DbCommand selectCommand = myConnection.CreateCommand();
selectCommand.CommandText
= "SELECT CategoryID, CategoryName FROM Categories;" +
"SELECT EmployeeID, LastName FROM Employees";

DbDataReader myReader
= selectCommand.ExecuteReader();

do
{
Console.WriteLine(
"\t{0}\t{1}", myReader.GetName(0), myReader.GetName(1));

while (myReader.Read())
Console.WriteLine(
"\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));

}
while (myReader.NextResult());

myReader.Close();

  当 DataReader 打开时,可以使用 GetSchemaTable 方法检索有关当前结果集的架构信息。对于结果集的每一列,DataTable 都将包含一行。架构表行的每一列都映射到在结果集中返回的列的属性,其中 ColumnName 是属性的名称,而列的值为属性的值。

DataTable schemaTable = myReader.GetSchemaTable();
       
foreach (DataRow myRow in schemaTable.Rows)
{
foreach (DataColumn myCol in schemaTable.Columns)
Console.WriteLine(myCol.ColumnName
+ " = " + myRow[myCol]);
Console.WriteLine();
}

4.从数据库中获取blob值

    DataReader 的默认行为是在整个数据行可用时立即以行的形式加载传入数据。但是,对于二进制大对象 (BLOB) 则需要进行不同的处理,因为它们可能包含数十亿字节的数据,而单个行中无法包含如此多的数据。Command.ExecuteReader 方法具有一个重载,它将采用 CommandBehavior 参数来修改 DataReader 的默认行为。您可以将 CommandBehavior.SequentialAccess 传递到 ExecuteReader 方法来修改 DataReader 的默认行为,
    以便让 DataReader 按照顺序在接收到数据时立即将其加载,而不是加载数据行。这是加载 BLOB 或其他大数据结构的理想方案。

  在将 DataReader 设置为使用 SequentialAccess 时,务必要注意访问所返回字段的顺序。DataReader 的默认行为是在整个行可用时立即加载该行,这使您能够在读取下一行之前按任何顺序访问所返回的字段。但是,当使用 SequentialAccess 时,必须按顺序访问由 DataReader 返回的不同字段。

  当访问 BLOB 字段中的数据时,请使用 DataReader 的 GetBytes 类型化访问器,该访问器将使用二进制数据填充 byte 数组。您可以指定要返回的特定数据缓冲区大小以及从返回的数据中读取的第一个字节的起始位置。GetBytes 将返回 long 值,它表示所返回的字节数。如果向 GetBytes 传递空的 byte 数组,所返回的长值将是 BLOB 中字节的总数。您可以选择将字节数组中的某索引指定为所读取数据的起始位置。 

FileStream fs; // 图片数据输出为文件
BinaryWriter bw; // 将二进制数据输出到文件流

int bufferSize = 100; // 缓冲区的大小
byte[] outbyte = new byte[bufferSize]; // 缓冲区
long retval; // 读取操作的返回值
long startIndex = 0; // 读取的起始位置

string pub_id = ""; // ID号,用来做文件的名字

SqlConnection pubsConn
= new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=pubs;");
// 创建命令,logo是我们要访问的二进制数据,是一张图片数据
SqlCommand logoCMD = new SqlCommand("SELECT pub_id, logo FROM pub_info", pubsConn);
// 打开数据库连接
pubsConn.Open();
// 执行查询操作,修改DataReader的默认行为
SqlDataReader myReader = logoCMD.ExecuteReader(CommandBehavior.SequentialAccess);

while (myReader.Read())
{
// 注意:必须按顺序读取,如果先读取myReader.GetString(1),将再不能读取myReader.GetString(0)
pub_id = myReader.GetString(0);

// 创建输出文件
fs = new FileStream("logo" + pub_id + ".bmp", FileMode.OpenOrCreate, FileAccess.Write);
bw
= new BinaryWriter(fs);

// 设置起始位置
startIndex = 0;

// 开始读取二进制信息,读入缓冲区
retval = myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize);

// 如果没有读取完毕,循环读取
while (retval == bufferSize)
{
bw.Write(outbyte);
bw.Flush();

// 重新设置起始位置
startIndex += bufferSize;
retval
= myReader.GetBytes(1, startIndex, outbyte, 0, bufferSize);
}

bw.Write(outbyte);
bw.Flush();

// 关闭流
bw.Close();
fs.Close();
}

// Close the reader and the connection.
myReader.Close();
pubsConn.Close();

5.使用DataAdapter填充DataSet

  ADO.NET DataSet 是数据的内存驻留表示形式,它提供了独立于数据源的一致关系编程模型。DataSet 表示整个数据集,其中包含表、约束和表之间的关系。由于 DataSet 独立于数据源,DataSet 可以包含应用程序本地的数据,也可以包含来自多个数据源的数据。与现有数据源的交互通过 DataAdapter 来控制。

// 建立连接
SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind");
// 建立命令
SqlCommand selectCMD = new SqlCommand("SELECT CustomerID, CompanyName FROM Customers", nwindConn);
selectCMD.CommandTimeout
= 30;
// 建立DataAdapter
SqlDataAdapter custDA = new SqlDataAdapter();
custDA.SelectCommand
= selectCMD;
// 打开连接
nwindConn.Open();
// 建立DataSet
DataSet custDS = new DataSet();
// 进行填充
custDA.Fill(custDS, "Customers");
// 关闭连接
nwindConn.Close();

  填充的结果是在DataSet 中创建表。如果 DataAdapter 遇到多个结果集,它将在 DataSet 中创建多个表。例子中指定了表的名字为“Customers”

  也可以多个DataAdapter填充一个DataSet

// 创建DataSet
DataSet custDS = new DataSet();

// 进行填充,指定表名字
custDA.Fill(custDS, "Customers");
orderDA.Fill(custDS,
"Orders");
// 添加表之间的关系,不是必须的,要看业务逻辑的需要。这里不细说。
DataRelation custOrderRel = custDS.Relations.Add("CustOrders", custDS.Tables["Customers"].Columns["CustomerID"], custDS.Tables["Orders"].Columns["CustomerID"]);
// 查看填充结果
foreach (DataRow pRow in custDS.Tables["Customers"].Rows)
{
Console.WriteLine(pRow[
"CustomerID"]);
foreach (DataRow cRow in pRow.GetChildRows(custOrderRel))
Console.WriteLine(
"\t" + cRow["OrderID"]);
}

posted on 2011-02-24 14:41  虎头工作室  阅读(303)  评论(0编辑  收藏  举报