Gegevens ophalen met behulp van een DataReader

Als u gegevens wilt ophalen met behulp van een DataReader, maakt u een exemplaar van het opdrachtobject en maakt u vervolgens een DataReader door Command.ExecuteReader aan te roepen om rijen op te halen uit een gegevensbron. De DataReader biedt een niet-gebufferde gegevensstroom waarmee procedurele logica resultaten van een gegevensbron opeenvolgend kan verwerken. De DataReader is een goede keuze wanneer u grote hoeveelheden gegevens opzoekt omdat de gegevens niet in de cache worden opgeslagen in het geheugen.

In het volgende voorbeeld ziet u hoe u een DataReader gebruikt, waarbij reader een geldig DataReader wordt aangegeven en command een geldig opdrachtobject vertegenwoordigt.

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

Gebruik de methode DataReader.Read om een rij op te halen uit de queryresultaten. U kunt elke kolom van de geretourneerde rij openen door de naam of het rangnummer van de kolom door te geven aan de DataReader. Voor de beste prestaties biedt DataReader echter een reeks methoden waarmee u toegang hebt tot kolomwaarden in hun systeemeigen gegevenstypen (GetDateTime, GetDouble, GetGuid, GetInt32, enzovoort). Zie en voor een lijst met getypte toegangsmethoden voor gegevensproviderspecifieke DataReadersOleDbDataReader.SqlDataReader Als u de getypte toegangsmethoden gebruikt wanneer u weet dat het onderliggende gegevenstype de hoeveelheid typeconversie vermindert die nodig is bij het ophalen van de kolomwaarde.

In het volgende voorbeeld wordt een DataReader-object herhaald en worden twee kolommen uit elke rij geretourneerd.

static void HasRows(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new(
          "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

De DataReader sluiten

Roep altijd de methode Sluiten aan wanneer u klaar bent met het DataReader-object .

Als uw opdracht uitvoerparameters of retourwaarden bevat, zijn deze waarden pas beschikbaar als de DataReader is gesloten.

Hoewel een DataReader is geopend, wordt de Verbinding maken ion uitsluitend door die DataReader gebruikt. U kunt geen opdrachten uitvoeren voor de Verbinding maken ion, waaronder het maken van een andere DataReader, totdat de oorspronkelijke DataReader is gesloten.

Notitie

Roep geen sluiten aan of verwijderen op een Verbinding maken ion, een DataReader of een ander beheerd object in de methode Finalize van uw klasse. In een finalizer kunt u alleen onbeheerde resources vrijgeven die rechtstreeks eigendom zijn van uw klasse. Als uw klasse geen onbeheerde resources heeft, moet u geen methode Voltooien in uw klassedefinitie opnemen. Zie Garbagecollection voor meer informatie.

Meerdere resultatensets ophalen met NextResult

Als de DataReader meerdere resultatensets retourneert, roept u de NextResult-methode aan om de resultatensets opeenvolgend te doorlopen. In het volgende voorbeeld ziet u de SqlDataReader verwerking van de resultaten van twee SELECT-instructies met behulp van de ExecuteReader methode.

static void RetrieveMultipleResults(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new(
          "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

Schemagegevens ophalen uit DataReader

Terwijl een DataReader is geopend, kunt u schemagegevens over de huidige resultatenset ophalen met behulp van de methode GetSchemaTable . GetSchemaTable retourneert een DataTable object dat is gevuld met rijen en kolommen die de schemagegevens voor de huidige resultatenset bevatten. De gegevenstabel bevat één rij voor elke kolom van de resultatenset. Elke kolom van de schematabel wordt toegewezen aan een eigenschap van de kolommen die worden geretourneerd in de rijen van de resultatenset, waarbij ColumnName de naam van de eigenschap is en de waarde van de kolom de waarde van de eigenschap is. In het volgende voorbeeld worden de schemagegevens voor DataReader weggeschreven.

static void GetSchemaInfo(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new(
          "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

Werken met OLE DB-hoofdstukken

Hiërarchische rijensets of hoofdstukken (OLE DB-type DBTYPE_HCHAPTER, ADO-type adChapter), kunnen worden opgehaald met behulp van de OleDbDataReader. Wanneer een query met een hoofdstuk wordt geretourneerd als een DataReader, wordt het hoofdstuk geretourneerd als een kolom in die DataReader en wordt weergegeven als een DataReader-object .

De ADO.NET DataSet kan ook worden gebruikt om hiërarchische rijensets weer te geven met behulp van bovenliggende en onderliggende relaties tussen tabellen. Zie DataSets, DataTables en DataViews voor meer informatie.

In het volgende codevoorbeeld wordt de MSDataShape-provider gebruikt om een hoofdstukkolom met orders te genereren voor elke klant in een lijst met klanten.

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

Resultaten retourneren met Oracle REF CURSORs

De .NET Framework-gegevensprovider voor Oracle ondersteunt het gebruik van Oracle REF CURSORs om een queryresultaat te retourneren. Een Oracle REF CURSOR wordt geretourneerd als een OracleDataReader.

U kunt een OracleDataReader object ophalen dat een Oracle REF CURSOR vertegenwoordigt met behulp van de ExecuteReader methode. U kunt ook een OracleCommand waarde opgeven die een of meer Oracle REF CURSORs retourneert als selectcommand voor een OracleDataAdapter gebruikt om een DataSet.

Als u toegang wilt krijgen tot een VERW CURSOR die is geretourneerd vanuit een Oracle-gegevensbron, maakt u een OracleCommand voor uw query en voegt u een uitvoerparameter toe die verwijst naar de REF CURSOR naar de Parameters verzameling van uw OracleCommand. De naam van de parameter moet overeenkomen met de naam van de parameter VERW CURSOR in uw query. Stel het type van de parameter in op OracleType.Cursor. De OracleCommand.ExecuteReader() methode van uw OracleCommand retourneert een OracleDataReader voor de VERW CURSOR.

Als u OracleCommand meerdere REF CURSORS retourneert, voegt u meerdere uitvoerparameters toe. U kunt toegang krijgen tot de verschillende REF CURSORs door de OracleCommand.ExecuteReader() methode aan te roepen. De aanroep om ExecuteReader() een OracleDataReader verwijzing naar de eerste VERW CURSOR te retourneren. Vervolgens kunt u de OracleDataReader.NextResult() methode aanroepen voor toegang tot volgende REF CURSORs. Hoewel de parameters in uw OracleCommand.Parameters verzameling overeenkomen met de REF CURSOR-uitvoerparameters op naam, worden deze OracleDataReader geopend in de volgorde waarin ze aan de Parameters verzameling zijn toegevoegd.

Denk bijvoorbeeld aan het volgende Oracle-pakket en de volgende hoofdtekst van het pakket.

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;

Met de volgende code maakt u een OracleCommand die de REF CURSORs van het vorige Oracle-pakket retourneert door twee parameters van het type OracleType.Cursor toe te voegen aan de OracleCommand.Parameters verzameling.

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;  

De volgende code retourneert de resultaten van de vorige opdracht met behulp van de Read() en NextResult() methoden van de OracleDataReader. De REF CURSOR-parameters worden in volgorde geretourneerd.

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

In het volgende voorbeeld wordt de vorige opdracht gebruikt om een DataSet met de resultaten van het Oracle-pakket te vullen.

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

Notitie

Om een OverflowException te voorkomen, raden we u aan ook elke conversie van het Oracle NUMBER-type naar een geldig .NET Framework-type te verwerken voordat u de waarde opslaat in een DataRow. U kunt de FillError gebeurtenis gebruiken om te bepalen of er een OverflowException is opgetreden. Zie DataAdapter-gebeurtenissen verwerken voor meer informatie over de FillError gebeurtenis.

Zie ook