按 DataReader 检索数据

适用于: .NET Framework .NET .NET Standard

下载 ADO.NET

若要使用 DataReader 检索数据,请创建 Command 对象的实例,然后通过调用 Command.ExecuteReader 创建一个 DataReader,以便从数据源检索行 。 DataReader 提供未缓冲的数据流,该数据流使过程逻辑可以有效地按顺序处理从数据源中返回的结果。

注意

由于数据不在内存中缓存,所以在检索大量数据时,DataReader 是一种适合的选择。

下面的示例演示如何使用 DataReader,其中 reader 表示有效的 DataReader,而 command 表示有效的 Command 对象。

reader = command.ExecuteReader();  

使用 DataReader.Read 方法从查询结果中获取行。 通过向 DataReader 传递列的名称或序号,可以访问返回行的每一列。 不过,为了实现最佳性能,DataReader 提供了一系列方法,将使你能够访问其本机数据类型(GetDateTime、GetDouble、GetGuid、GetInt32 等)的列值 。 有关数据提供程序特定的 DataReaders 的类型化访问器方法列表,请参阅 SqlDataReader。 已知基础数据类型时,如果使用类型化访问器方法,将减少在检索列值时所需的类型转换量。

以下示例循环访问一个 DataReader 对象,并从每个行中返回两个列。

static void HasRows(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "SELECT CategoryID, CategoryName FROM Categories;",
          connection);
        connection.Open();

        SqlDataReader reader = command.ExecuteReader();

        // Check if the DataReader has any row.
        if (reader.HasRows)
        {
            // Obtain a row from the query result.
            while (reader.Read())
            {
                Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
                    reader.GetString(1));
            }
        }
        else
        {
            Console.WriteLine("No rows found.");
        }
        // Always call the Close method when you have finished using the DataReader object.
        reader.Close();
    }
}

关闭 DataReader

使用完 DataReader 对象后,请始终调用 Close() 方法。

注意

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

重要

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

备注

不要在类的 Finalize 方法中对 Connection、DataReader 或任何其他托管对象调用 Close 或 Dispose 。 在终结器中,仅释放类直接拥有的非托管资源。 如果类不拥有任何非托管资源,则不要在类定义中包含 Finalize 方法。 有关详细信息,请参阅垃圾回收

使用 NextResult 检索多个结果集

如果 DataReader 返回多个结果集,请调用 NextResult 方法来按顺序循环访问这些结果集 。 以下示例显示 SqlDataReader 如何使用 ExecuteReader 方法处理两个 SELECT 语句的结果。

static void RetrieveMultipleResults(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "SELECT CategoryID, CategoryName FROM dbo.Categories;" +
          "SELECT EmployeeID, LastName FROM dbo.Employees",
          connection);
        connection.Open();

        SqlDataReader reader = command.ExecuteReader();

        // Check if the DataReader has any row.
        while (reader.HasRows)
        {
            Console.WriteLine("\t{0}\t{1}", reader.GetName(0),
                reader.GetName(1));

            // Obtain a row from the query result.
            while (reader.Read())
            {
                Console.WriteLine("\t{0}\t{1}", reader.GetInt32(0),
                    reader.GetString(1));
            }

            // Hop to the next result-set.
            reader.NextResult();
        }
        // Always call the Close method when you have finished using the DataReader object.
        reader.Close();
    }
}

从 DataReader 中获取架构信息

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

static void GetSchemaInfo(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "SELECT CategoryID, CategoryName FROM Categories;",
          connection);
        connection.Open();

        SqlDataReader reader = command.ExecuteReader();

        // Retrieve schema information about the current result-set.
        DataTable schemaTable = reader.GetSchemaTable();

        foreach (DataRow row in schemaTable.Rows)
        {
            foreach (DataColumn column in schemaTable.Columns)
            {
                Console.WriteLine(String.Format("{0} = {1}",
                   column.ColumnName, row[column]));
            }
        }

        // Always call the Close method when you have finished using the DataReader object.
        reader.Close();
    }
}

另请参阅