Abrufen von Daten mit einem DataReaderRetrieve data using a DataReader

Erstellen Sie zum Abrufen von Daten mithilfe eines DataReader-Objekts eine Instanz des Befehls Objekts, und erstellen Sie dann einen DataReader , indem Sie Command. ExecuteReader aufrufen, um Zeilen aus einer Datenquelle abzurufen.To retrieve data using a DataReader, create an instance of the Command object, and then create a DataReader by calling Command.ExecuteReader to retrieve rows from a data source. Das DataReader -Objekt stellt einen nicht gepufferten Datenstrom bereit, der prozeduralen Logik die effiziente Verarbeitung von Ergebnissen aus einer Datenquelle in sequenziell ermöglicht.The DataReader provides an unbuffered stream of data that allows procedural logic to efficiently process results from a data source sequentially. Der DataReader ist eine gute Wahl, wenn Sie große Datenmengen abrufen, da die Daten nicht im Arbeitsspeicher zwischengespeichert werden.The DataReader is a good choice when you're retrieving large amounts of data because the data is not cached in memory.

Das folgende Beispiel veranschaulicht die Verwendung eines DataReader, reader wobei einen gültigen DataReader darstellt command und ein gültiges Befehls Objekt darstellt.The following example illustrates using a DataReader, where reader represents a valid DataReader and command represents a valid Command object.

reader = command.ExecuteReader();  
reader = command.ExecuteReader()

Verwenden Sie die DataReader. Read -Methode, um eine Zeile aus den Abfrage Ergebnissen zu erhalten.Use the DataReader.Read method to obtain a row from the query results. Sie können auf jede Spalte der zurückgegebenen Zeile zugreifen, indem Sie den Namen oder die Ordinalzahl der Spalte an den DataReaderübergeben.You can access each column of the returned row by passing the name or ordinal number of the column to the DataReader. Um die bestmögliche Leistung zu erzielen, stellt der DataReader eine Reihe von Methoden bereit, mit denen Sie auf Spaltenwerte in ihren systemeigenen Datentypen (GetDateTime, GetDouble, GetGuid, GetInt32usw.) zugreifen können.However, for best performance, the DataReader provides a series of methods that allow you to access column values in their native data types (GetDateTime, GetDouble, GetGuid, GetInt32, and so on). Eine Liste der typisierten Accessormethoden für Datenanbieter spezifische DataReadersfinden OleDbDataReader Sie unter und SqlDataReader.For a list of typed accessor methods for data provider-specific DataReaders, see OleDbDataReader and SqlDataReader. Wenn Sie die typisierten Accessormethoden verwenden, wenn Sie wissen, dass der zugrunde liegende Datentyp beim Abrufen des Spaltenwerts die erforderliche Typkonvertierung reduziert.Using the typed accessor methods when you know the underlying data type reduces the amount of type conversion required when retrieving the column value.

Im folgenden Beispiel wird ein DataReader -Objekt durchlaufen, und es werden zwei Spalten aus jeder Zeile zurückgegeben.The following example iterates through a DataReader object and returns two columns from each row.

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

        SqlDataReader reader = command.ExecuteReader();

        if (reader.HasRows)
        {
            while (reader.Read())
            {
                Console.WriteLine("{0}\t{1}", reader.GetInt32(0),
                    reader.GetString(1));
            }
        }
        else
        {
            Console.WriteLine("No rows found.");
        }
        reader.Close();
    }
}
Private Sub HasRows(ByVal connection As SqlConnection)
    Using connection
        Dim command As SqlCommand = New SqlCommand( _
          "SELECT CategoryID, CategoryName FROM Categories;", _
          connection)
        connection.Open()

        Dim reader As SqlDataReader = command.ExecuteReader()

        If reader.HasRows Then
            Do While reader.Read()
                Console.WriteLine(reader.GetInt32(0) _
                  & vbTab & reader.GetString(1))
            Loop
        Else
            Console.WriteLine("No rows found.")
        End If

        reader.Close()
    End Using
End Sub

Schließen des "DataReader"Closing the DataReader

Verwenden Sie immer die Close -Methode, wenn Sie das DataReader -Objekt nicht mehr benötigen.Always call the Close method when you have finished using the DataReader object.

Wenn der Befehl Ausgabeparameter oder Rückgabewerte enthält, sind diese Werte erst nach dem Schließen des DataReader verfügbar.If your Command contains output parameters or return values, those values are not available until the DataReader is closed.

Während ein DataReader geöffnet ist, wird die Verbindung exklusiv von diesem DataReaderverwendet.While a DataReader is open, the Connection is in use exclusively by that DataReader. Sie können keine Befehle für die Verbindungausführen, einschließlich der Erstellung eines anderen DataReader, bis der ursprüngliche DataReader geschlossen wird.You cannot execute any commands for the Connection, including creating another DataReader, until the original DataReader is closed.

Hinweis

Führen Sie in der Finalize -Methode der Klasse nicht Close oder verwerfen für eine Verbindung, einen DataReader oder ein anderes verwaltetes Objekt aus.Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. Geben Sie in einer Finalize-Methode nur nicht verwaltete Ressourcen frei, die der Klasse direkt gehören.In a finalizer, only release unmanaged resources that your class owns directly. Wenn Ihre Klasse keine nicht verwalteten Ressourcen besitzt, schließen Sie keine Finalize -Methode in die Klassendefinition ein.If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. Weitere Informationen finden Sie unter Garbage Collection.For more information, see Garbage Collection.

Abrufen mehrerer Resultsets mithilfe von NextResultRetrieving multiple result sets using NextResult

Wenn das DataReader -Objekt mehrere Resultsets zurückgibt, wird die NextResult -Methode aufgerufen, um die Resultsets sequenziell zu durchlaufen.If the DataReader returns multiple result sets, call the NextResult method to iterate through the result sets sequentially. Im folgenden Beispiel werden die Ergebnisse von zwei SELECT-Anweisungen mit der SqlDataReader-Methode von ExecuteReader verarbeitet.The following example shows the SqlDataReader processing the results of two SELECT statements using the ExecuteReader method.

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();

        while (reader.HasRows)
        {
            Console.WriteLine("\t{0}\t{1}", reader.GetName(0),
                reader.GetName(1));

            while (reader.Read())
            {
                Console.WriteLine("\t{0}\t{1}", reader.GetInt32(0),
                    reader.GetString(1));
            }
            reader.NextResult();
        }
    }
}
Private Sub RetrieveMultipleResults(ByVal connection As SqlConnection)
    Using connection
        Dim command As SqlCommand = New SqlCommand( _
          "SELECT CategoryID, CategoryName FROM Categories;" & _
          "SELECT EmployeeID, LastName FROM Employees", connection)
        connection.Open()

        Dim reader As SqlDataReader = command.ExecuteReader()

        Do While reader.HasRows
            Console.WriteLine(vbTab & reader.GetName(0) _
              & vbTab & reader.GetName(1))

            Do While reader.Read()
                Console.WriteLine(vbTab & reader.GetInt32(0) _
                  & vbTab & reader.GetString(1))
            Loop

            reader.NextResult()
        Loop
    End Using
End Sub

Erhalten von Schema Informationen aus dem DataReaderGetting schema information from the DataReader

Während ein DataReader geöffnet ist, können Sie Schema Informationen über das aktuelle Resultset mithilfe der getschembare -Methode abrufen.While a DataReader is open, you can retrieve schema information about the current result set using the GetSchemaTable method. Getschemabel gibt ein DataTable -Objekt zurück, das mit Zeilen und Spalten aufgefüllt ist, die die Schema Informationen für das aktuelle Resultset enthalten.GetSchemaTable returns a DataTable object populated with rows and columns that contain the schema information for the current result set. Die Daten Tabelle enthält eine Zeile für jede Spalte des Resultsets.The DataTable contains one row for each column of the result set. Jede Spalte der Schema Tabelle ist einer Eigenschaft der Spalten zugeordnet, die in den Zeilen des Resultsets zurückgegeben werden, wobei ColumnName der Name der Eigenschaft und der Wert der Spalte der Wert der Eigenschaft ist.Each column of the schema table maps to a property of the columns returned in the rows of the result set, where the ColumnName is the name of the property and the value of the column is the value of the property. Im folgenden Beispiel werden die Schema Informationen für DataReadergeschrieben.The following example writes out the schema information for DataReader.

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

        SqlDataReader reader = command.ExecuteReader();
        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]));
            }
        }
    }
}
Private Sub GetSchemaInfo(ByVal connection As SqlConnection)
    Using connection
        Dim command As SqlCommand = New SqlCommand( _
          "SELECT CategoryID, CategoryName FROM Categories;", _
          connection)
        connection.Open()

        Dim reader As SqlDataReader = command.ExecuteReader()
        Dim schemaTable As DataTable = reader.GetSchemaTable()

        Dim row As DataRow
        Dim column As DataColumn

        For Each row In schemaTable.Rows
            For Each column In schemaTable.Columns
                Console.WriteLine(String.Format("{0} = {1}", _
                  column.ColumnName, row(column)))
            Next
            Console.WriteLine()
        Next
        reader.Close()
    End Using
End Sub

Arbeiten mit OLE DB KapitelnWorking with OLE DB chapters

Hierarchische Rowsets oder Kapitel (OLE DB Type DBTYPE_HCHAPTER, ADO Type adChapter) können mithilfe von OleDbDataReaderabgerufen werden.Hierarchical rowsets, or chapters (OLE DB type DBTYPE_HCHAPTER, ADO type adChapter), can be retrieved using the OleDbDataReader. Wenn eine Abfrage, die ein Kapitel enthält, als DataReaderzurückgegeben wird, wird das Kapitel als Spalte in diesem DataReader zurückgegeben und als DataReader -Objekt verfügbar gemacht.When a query that includes a chapter is returned as a DataReader, the chapter is returned as a column in that DataReader and is exposed as a DataReader object.

Das ADO.net- DataSet kann auch verwendet werden, um hierarchische Rowsets mithilfe von über-und untergeordneten Beziehungen zwischen Tabellen darzustellen.The ADO.NET DataSet can also be used to represent hierarchical rowsets by using parent-child relationships between tables. Weitere Informationen finden Sie unter Datasets, DataTables und DataViews.For more information, see DataSets, DataTables, and DataViews.

Im folgenden Codebeispiel wird mit dem MSDataShape-Anbieter eine Kapitelspalte mit Bestellungen für jeden Kunden in einer Kundenliste generiert.The following code example uses the MSDataShape Provider to generate a chapter column of orders for each customer in a list of customers.

Using connection As OleDbConnection = New OleDbConnection(
    "Provider=MSDataShape;Data Provider=SQLOLEDB;" &
    "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")

    Using custCMD As OleDbCommand = New OleDbCommand(
        "SHAPE {SELECT CustomerID, CompanyName FROM Customers} " &
        "APPEND ({SELECT CustomerID, OrderID FROM Orders} AS CustomerOrders " &
        "RELATE CustomerID TO CustomerID)", connection)

        connection.Open()

        Using custReader As OleDbDataReader = custCMD.ExecuteReader()

            Do While custReader.Read()
                Console.WriteLine("Orders for " & custReader.GetString(1))
                ' custReader.GetString(1) = CompanyName  

                Using orderReader As OleDbDataReader = custReader.GetValue(2)
                    ' custReader.GetValue(2) = Orders chapter as DataReader  

                    Do While orderReader.Read()
                        Console.WriteLine(vbTab & orderReader.GetInt32(1))
                        ' orderReader.GetInt32(1) = OrderID  
                    Loop
                    orderReader.Close()
                End Using
            Loop
            ' Make sure to always close readers and connections.  
            custReader.Close()
        End Using
    End Using
End Using
using (OleDbConnection connection = new OleDbConnection(
    "Provider=MSDataShape;Data Provider=SQLOLEDB;" +
    "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"))
{
    using (OleDbCommand custCMD = new OleDbCommand(
        "SHAPE {SELECT CustomerID, CompanyName FROM Customers} " +
        "APPEND ({SELECT CustomerID, OrderID FROM Orders} AS CustomerOrders " +
        "RELATE CustomerID TO CustomerID)", connection))
    {
        connection.Open();

        using (OleDbDataReader custReader = custCMD.ExecuteReader())
        {

            while (custReader.Read())
            {
                Console.WriteLine("Orders for " + custReader.GetString(1));
                // custReader.GetString(1) = CompanyName  

                using (OleDbDataReader orderReader = (OleDbDataReader)custReader.GetValue(2))
                {
                    // custReader.GetValue(2) = Orders chapter as DataReader  

                    while (orderReader.Read())
                        Console.WriteLine("\t" + orderReader.GetInt32(1));
                    // orderReader.GetInt32(1) = OrderID  
                    orderReader.Close();
                }
            }
            // Make sure to always close readers and connections.  
            custReader.Close();
        }
    }
}

Zurückgeben von Ergebnissen mit Oracle-REF CursorsReturning results with Oracle REF CURSORs

Der .NET Framework-Datenanbieter für Oracle unterstützt die Verwendung von Oracle-REF CURSORs zur Rückgabe eines Abfrageergebnisses.The .NET Framework Data Provider for Oracle supports the use of Oracle REF CURSORs to return a query result. Ein Oracle-REF CURSOR wird als OracleDataReader zurückgegeben.An Oracle REF CURSOR is returned as an OracleDataReader.

Sie können ein OracleDataReader Objekt, das einen Oracle-REF-Cursor darstellt, ExecuteReader mithilfe der-Methode abrufen.You can retrieve an OracleDataReader object that represents an Oracle REF CURSOR by using the ExecuteReader method. Sie OracleCommand können auch einen angeben, der einen oder mehrere Oracle-REF Cursors als SelectCommand für einen OracleDataAdapter zurückgibt, der zum Ausfüllen eines DataSetverwendet wird.You can also specify an OracleCommand that returns one or more Oracle REF CURSORs as the SelectCommand for an OracleDataAdapter used to fill a DataSet.

Um auf einen von einer Oracle-Datenquelle zurückgegebenen Verweis Cursor zuzugreifen OracleCommand , erstellen Sie einen für die Abfrage, und fügen Sie einen Output-Parameter Parameters hinzu, der OracleCommandauf den Verweis Cursor auf die-Auflistung Ihres verweist.To access a REF CURSOR returned from an Oracle data source, create an OracleCommand for your query and add an output parameter that references the REF CURSOR to the Parameters collection of your OracleCommand. Der Name des Parameters muss mit dem Namen des REF CURSOR-Parameters in der Abfrage übereinstimmen.The name of the parameter must match the name of the REF CURSOR parameter in your query. Legen Sie den Typ des Parameters OracleType.Cursorauf fest.Set the type of the parameter to OracleType.Cursor. Die OracleCommand.ExecuteReader() -Methode OracleCommand des gibt einen OracleDataReader für den ref Cursor zurück.The OracleCommand.ExecuteReader() method of your OracleCommand returns an OracleDataReader for the REF CURSOR.

Wenn Sie OracleCommand mehrere Ref Cursors zurückgibt, fügen Sie mehrere Ausgabeparameter hinzu.If your OracleCommand returns multiple REF CURSORS, add multiple output parameters. Sie können auf die verschiedenen REF CURSORs zugreifen, indem OracleCommand.ExecuteReader() Sie die-Methode aufrufen.You can access the different REF CURSORs by calling the OracleCommand.ExecuteReader() method. Der-Rückruf ExecuteReader() gibt einen OracleDataReader zurück, der auf den ersten Verweis Cursor verweist.The call to ExecuteReader() returns an OracleDataReader referencing the first REF CURSOR. Sie können dann die OracleDataReader.NextResult() -Methode aufrufen, um auf nachfolgende Ref Cursors zuzugreifen.You can then call the OracleDataReader.NextResult() method to access subsequent REF CURSORs. Obwohl die Parameter in OracleCommand.Parameters der Auflistung den REF CURSOR-Ausgabeparametern nach Namen entsprechen, greift der OracleDataReader in der Reihenfolge, in der Parameters Sie der Auflistung hinzugefügt wurden, auf Sie zu.Although the parameters in your OracleCommand.Parameters collection match the REF CURSOR output parameters by name, the OracleDataReader accesses them in the order in which they were added to the Parameters collection.

Betrachten Sie z. B. das folgende Oracle-Paket und den Paketkörper.For example, consider the following Oracle package and package body.

CREATE OR REPLACE PACKAGE CURSPKG AS   
  TYPE T_CURSOR IS REF CURSOR;   
  PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,   
    DEPTCURSOR OUT T_CURSOR);   
END CURSPKG;  
  
CREATE OR REPLACE PACKAGE BODY CURSPKG AS   
  PROCEDURE OPEN_TWO_CURSORS (EMPCURSOR OUT T_CURSOR,   
    DEPTCURSOR OUT T_CURSOR)   
  IS   
  BEGIN   
    OPEN EMPCURSOR FOR SELECT * FROM DEMO.EMPLOYEE;   
    OPEN DEPTCURSOR FOR SELECT * FROM DEMO.DEPARTMENT;   
  END OPEN_TWO_CURSORS;   
END CURSPKG;   

Der folgende Code erstellt eine OracleCommand , die die Ref Cursors aus dem vorherigen Oracle-Paket zurückgibt, indem der OracleType.Cursor OracleCommand.Parameters -Auflistung zwei Parameter des Typs hinzugefügt werden.The following code creates an OracleCommand that returns the REF CURSORs from the previous Oracle package by adding two parameters of type OracleType.Cursor to the OracleCommand.Parameters collection.

Dim cursCmd As OracleCommand = New OracleCommand("CURSPKG.OPEN_TWO_CURSORS", oraConn)  
cursCmd.Parameters.Add("EMPCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output  
cursCmd.Parameters.Add("DEPTCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output  
OracleCommand cursCmd = new OracleCommand("CURSPKG.OPEN_TWO_CURSORS", oraConn);  
cursCmd.Parameters.Add("EMPCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output;  
cursCmd.Parameters.Add("DEPTCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output;  

Der folgende Code gibt die Ergebnisse des vorherigen Befehls mithilfe der Read() -Methode und der- OracleDataReader NextResult() Methode von zurück.The following code returns the results of the previous command using the Read() and NextResult() methods of the OracleDataReader. Die REF CURSOR-Parameter werden der Reihe nach zurückgegeben.The REF CURSOR parameters are returned in order.

oraConn.Open()  
  
Dim cursCmd As OracleCommand = New OracleCommand("CURSPKG.OPEN_TWO_CURSORS", oraConn)  
cursCmd.CommandType = CommandType.StoredProcedure  
cursCmd.Parameters.Add("EMPCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output  
cursCmd.Parameters.Add("DEPTCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output  
  
Dim reader As OracleDataReader = cursCmd.ExecuteReader()  
  
Console.WriteLine(vbCrLf & "Emp ID" & vbTab & "Name")  
  
Do While reader.Read()  
  Console.WriteLine("{0}" & vbTab & "{1}, {2}", reader.GetOracleNumber(0), reader.GetString(1), reader.GetString(2))  
Loop  
  
reader.NextResult()  
  
Console.WriteLine(vbCrLf & "Dept ID" & vbTab & "Name")  
  
Do While reader.Read()  
  Console.WriteLine("{0}" & vbTab & "{1}", reader.GetOracleNumber(0), reader.GetString(1))  
Loop  
' Make sure to always close readers and connections.  
reader.Close()  
oraConn.Close()  
oraConn.Open();  
  
OracleCommand cursCmd = new OracleCommand("CURSPKG.OPEN_TWO_CURSORS", oraConn);  
cursCmd.CommandType = CommandType.StoredProcedure;  
cursCmd.Parameters.Add("EMPCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output;  
cursCmd.Parameters.Add("DEPTCURSOR", OracleType.Cursor).Direction = ParameterDirection.Output;  
  
OracleDataReader reader = cursCmd.ExecuteReader();  
  
Console.WriteLine("\nEmp ID\tName");  
  
while (reader.Read())  
  Console.WriteLine("{0}\t{1}, {2}", reader.GetOracleNumber(0), reader.GetString(1), reader.GetString(2));  
  
reader.NextResult();  
  
Console.WriteLine("\nDept ID\tName");  
  
while (reader.Read())  
  Console.WriteLine("{0}\t{1}", reader.GetOracleNumber(0), reader.GetString(1));  
// Make sure to always close readers and connections.  
reader.Close();  
oraConn.Close();  

Im folgenden Beispiel wird der vorherige Befehl verwendet, um eine DataSet mit den Ergebnissen des Oracle-Pakets aufzufüllen.The following example uses the previous command to populate a DataSet with the results of the Oracle package.

Dim ds As DataSet = New DataSet()  
  
Dim adapter As OracleDataAdapter = New OracleDataAdapter(cursCmd)  
adapter.TableMappings.Add("Table", "Employees")  
adapter.TableMappings.Add("Table1", "Departments")  
  
adapter.Fill(ds)  
DataSet ds = new DataSet();  
  
OracleDataAdapter adapter = new OracleDataAdapter(cursCmd);  
adapter.TableMappings.Add("Table", "Employees");  
adapter.TableMappings.Add("Table1", "Departments");  
  
adapter.Fill(ds);  

Hinweis

Um eine OverflowExceptionzu vermeiden, empfiehlt es sich, jede beliebige Konvertierung vom Oracle-Nummertyp in einen gültigen .NET Framework Typ zu verarbeiten, bevor der DataRowWert in einer gespeichert wird.To avoid an OverflowException, we recommend that you also handle any conversion from the Oracle NUMBER type to a valid .NET Framework type before storing the value in a DataRow. Sie können das FillError -Ereignis verwenden, um zu bestimmen, ob eine OverflowException aufgetreten ist.You can use the FillError event to determine if an OverflowException has occurred. Weitere Informationen FillError zum-Ereignis finden Sie unter Handling DataAdapter-Ereignisse.For more information on the FillError event, see Handling DataAdapter Events.

Siehe auchSee also