Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Wenn Sie Daten mit einem DataReader-Objekt abrufen möchten, müssen Sie zunächst eine Instanz des Command-Objekts und anschließend ein DataReader-Objekt erstellen, indem Sie Command.ExecuteReader aufrufen, um Zeilen aus einer Datenquelle abzurufen. Das DataReader-Objekt stellt einen ungepufferten Datenstrom bereit, mit dem prozeduraler Logik eine effektive sequenzielle Verarbeitung der Ergebnisse aus einer Datenquelle ermöglicht wird. Das DataReader-Objekt ist gut für das Abrufen großer Datenmengen geeignet, da die Daten nicht im Arbeitsspeicher zwischengespeichert werden.
Im folgenden Beispiel wird die Verwendung eines DataReader-Objekts gezeigt, wobei reader
für ein gültiges DataReader-Objekt und command
für ein gültiges Command-Objekt steht.
reader = command.ExecuteReader();
reader = command.ExecuteReader()
Verwenden Sie die DataReader.Read-Methode, um eine Zeile aus den Abfrageergebnissen abzurufen. Sie können auf jede Spalte der zurückgegebenen Zeile zugreifen, indem Sie dem DataReader-Objekt den Namen oder die Ordinalzahl der Spalte übergeben. Die beste Leistung erzielen Sie jedoch, wenn Sie die vom DataReader-Objekt bereitgestellten Methoden verwenden, mit denen Sie auf Spaltenwerte in ihren nativen Datentypen zugreifen können (z. B. GetDateTime, GetDouble, GetGuid oder GetInt32). Eine Liste der typierten Accessormethoden für datenanbieterspezifische DataReaders finden Sie unter OleDbDataReader und SqlDataReader. Mit den typisierten Accessormethoden wird die Menge der beim Abrufen des Spaltenwerts erforderlichen Typkonvertierungen reduziert, wenn der zugrunde liegende Datentyp bekannt ist.
Im folgenden Beispiel wird ein DataReader-Objekt durchlaufen, wobei von jeder Zeile zwei Spalten zurückgegeben werden.
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($"{reader.GetInt32(0)}\t{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
Rufen Sie immer die Close-Methode auf, wenn Sie die Verwendung des DataReader-Objekts abgeschlossen haben.
Wenn Ihr Command-Objekt Ausgabeparameter oder Rückgabewerte enthält, sind diese Werte erst nach dem Schließen des DataReader-Objekts verfügbar.
Solange ein DataReader-Objekt geöffnet ist, wird das Connection-Objekt ausschließlich von diesem DataReader-Objekt verwendet. Sie können erst dann Befehle für das Connection-Objekt ausführen, z. B. um ein anderes DataReader-Objekt zu erstellen, wenn das ursprüngliche DataReader-Objekt geschlossen wurde.
Hinweis
Rufen Sie Close oder Dispose nicht für Connection- oder DataReader-Objekte oder andere verwaltete Objekte in der Finalize-Methode Ihrer Klasse auf. Geben Sie in einer Finalize-Methode nur nicht verwaltete Ressourcen frei, die der Klasse direkt gehören. Wenn Ihre Klasse keine nicht verwalteten Ressourcen aufweist, verwenden Sie in Ihrer Klassendefinition keine Finalize-Methode. Weitere Informationen finden Sie unter Garbage Collection.
Abrufen mehrerer Resultsets mithilfe von NextResult
Wenn das DataReader-Objekt mehrere Resultsets zurückgibt, rufen Sie die NextResult-Methode auf, um die Resultsets nacheinander zu durchlaufen. Im folgenden Beispiel werden die Ergebnisse von zwei SELECT-Anweisungen mit der SqlDataReader-Methode von ExecuteReader verarbeitet.
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{reader.GetName(0)}\t{reader.GetName(1)}");
while (reader.Read())
{
Console.WriteLine($"\t{reader.GetInt32(0)}\t{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
Abrufen von Schemainformationen vom DataReader
Solange ein DataReader-Objekt geöffnet ist, können Sie mit der GetSchemaTable-Methode Schemainformationen zum aktuellen Resultset abrufen. GetSchemaTable gibt ein DataTable-Objekt zurück, das mit Zeilen und Spalten gefüllt ist, die die Schemainformationen für das aktuelle Resultset enthalten. Das DataTable-Objekt enthält eine Zeile für jede Spalte des Resultsets. Jede Spalte der Schematabelle ist einer Eigenschaft der zurückgegebenen Spalten in den Zeilen des Resultsets zugeordnet, wobei ColumnName der Name der Eigenschaft und der Spaltenwert der Wert der Eigenschaft ist. Im folgenden Beispiel werden die Schemainformationen für DataReader abgerufen.
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
Arbeiten mit OLE DB-Kapiteln
Hierarchische Rowsets oder Kapitel (OLE DB-Typ DBTYPE_HCHAPTER, ADO-Typ adChapter) können mithilfe des OleDbDataReader abgerufen werden. Wenn eine Abfrage, die ein Kapitel enthält, als DataReader zurückgegeben wird, wird das Kapitel als Spalte in diesem DataReader zurückgegeben und als DataReader-Objekt verfügbar gemacht.
Das ADO.NET DataSet kann auch verwendet werden, um hierarchische Rowsets durch Eltern-Kind-Beziehungen zwischen Tabellen darzustellen. Weitere Informationen finden Sie unter DataSets, DataTables und DataViews.
Im folgenden Codebeispiel wird der MSDataShape-Anbieter verwendet, um eine Kapitelspalte mit Bestellungen für jeden Kunden in einer Kundenliste zu generieren.
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 CURSORs
Der .NET Framework-Datenanbieter für Oracle unterstützt die Verwendung von Oracle REF CURSORs, um ein Abfrageergebnis zurückzugeben. Ein Oracle REF CURSOR wird als ein OracleDataReader zurückgegeben.
Sie können ein OracleDataReader Objekt abrufen, das einen Oracle REF CURSOR darstellt, indem Sie die ExecuteReader Methode verwenden. Außerdem können Sie für ein OracleCommand-Objekt, das zum Auffüllen von verwendet wird, ein OracleDataAdapter-Objekt angeben, das den REF CURSOR-Datentyp von Oracle als DataSet zurückgibt.
Um auf einen von einer Oracle-Datenquelle zurückgegebenen REF CURSOR zuzugreifen, erstellen Sie ein OracleCommand für Ihre Abfrage und fügen Sie einen Ausgabeparameter hinzu, der auf den REF CURSOR in der Parameters-Sammlung Ihres OracleCommand verweist. Der Name des Parameters muss mit dem Namen des REF CURSOR-Parameters in Ihrer Abfrage übereinstimmen. Legen Sie den Typ des Parameters auf OracleType.Cursor. Die OracleCommand.ExecuteReader()-Methode von OracleCommand gibt OracleDataReader für REF CURSOR zurück.
Wenn ihr OracleCommand mehrere REF CURSORS zurückgibt, fügen Sie mehrere Ausgabeparameter hinzu. Sie können auf die verschiedenen REF CURSORs zugreifen, indem Sie die OracleCommand.ExecuteReader() Methode aufrufen. Der Aufruf von ExecuteReader() gibt einen OracleDataReader zurück, der auf den ersten REF CURSOR-Datentyp verweist. Anschließend können Sie die OracleDataReader.NextResult() Methode aufrufen, um auf nachfolgende REF CURSORs zuzugreifen. Obwohl die Parameter in Ihrer OracleCommand.Parameters Auflistung den REF CURSOR-Ausgabeparametern nach Namen entsprechen, greift dies OracleDataReader auf sie in der Reihenfolge zu, in der sie der Parameters Auflistung hinzugefügt wurden.
Betrachten Sie z. B. das folgende Oracle-Paket und den Pakettext.
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;
Mit dem folgenden Code wird ein OracleCommand-Objekt erstellt, das die REF CURSORs aus dem vorherigen Oracle-Paket zurückgibt, indem der OracleType.Cursor-Sammlung zwei Parameter vom Typ OracleCommand.Parameters hinzugefügt werden.
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;
Im folgenden Code werden die Ergebnisse des vorherigen Befehls mithilfe der Methode Read() und NextResult() von OracleDataReader zurückgegeben. Die REF CURSOR-Parameter werden in der Reihenfolge zurückgegeben.
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 ein DataSet Element mit den Ergebnissen des Oracle-Pakets aufzufüllen.
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 OverflowException zu vermeiden, empfehlen wir Ihnen, auch die Konvertierung vom Oracle NUMBER-Typ in einen gültigen .NET Framework-Typ vorzunehmen, bevor Sie den Wert in einem DataRow speichern. Mit dem FillError Ereignis können Sie ermitteln, ob eine OverflowException aufgetreten ist. Weitere Informationen zum FillError Ereignis finden Sie unter Behandeln von DataAdapter-Ereignissen.