Sdílet prostřednictvím


Načtení dat pomocí třídy DataReader

Chcete-li načíst data pomocí DataReader, vytvořte instanci objektu Command a pak vytvořte DataReadervoláním Command.ExecuteReader pro načtení řádků ze zdroje dat. DataReader poskytuje neukládaný do vyrovnávací paměti datový proud, který umožňuje procedurální logice efektivně zpracovávat výsledky ze zdroje dat postupně. Je DataReader dobrou volbou při načítání velkých objemů dat, protože data nejsou uložená v mezipaměti.

Následující příklad ukazuje použití DataReader, kde reader představuje platný DataReader a command představuje platný Command objekt.

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

K získání řádku z výsledků dotazu použijte metodu DataReader.Read . Ke každému sloupci vráceného řádku můžete přistupovat předáním názvu nebo pořadového čísla sloupce do DataReader. Pro zajištění nejlepšího výkonu DataReader však poskytuje řadu metod, které umožňují přístup k hodnotám sloupců v jejich nativních datových typech (GetDateTime, GetDouble, GetGuid, GetInt32 atd.). Pro seznam typových přístupových metod pro DataReadery specifické pro zprostředkovatele dat vizte OleDbDataReader a SqlDataReader. Použití metod typového přístupu, když znáte základní datový typ, snižuje potřebu převodu typů při načítání hodnoty sloupce.

Následující příklad iteruje objektem DataReader a vrátí dva sloupce z každého řádku.

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

Zavření čtečky dat

Vždy volejte metodu Close po dokončení použití objektu DataReader .

Pokud vaše Command obsahuje výstupní parametry nebo návratové hodnoty, tyto hodnoty nejsou dostupné, dokud se DataReader nezavře.

Jakmile je DataReader otevřena, Connection se používá výhradně tím DataReader. Nelze spustit žádné příkazy pro připojení, včetně vytvoření jiného Objektu DataReader, dokud nebude původní DataReader zavřený.

Poznámka:

Nevyvolávejte ani Close nevolejte Disposepřipojení, DataReader ani žádný jiný spravovaný objekt v Finalize metodě vaší třídy. V finalizátoru uvolněte pouze nespravované prostředky, které vaše třída vlastní přímo. Pokud vaše třída nevlastní žádné nespravované prostředky, nezahrnujte do definice třídy metodu Finalize . Další informace naleznete v tématu Uvolňování paměti.

Načítání více sad výsledků pomocí nextResult

DataReader Pokud vrátí více sad výsledků, zavolejte metoduNextResult, která iteruje sady výsledků postupně. Následující příklad ukazuje, jak SqlDataReader zpracovává výsledky dvou příkazů SELECT metodou ExecuteReader.

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

Získání informací o schématu z modulu DataReader

Zatímco je DataReader otevřená, můžete pomocí metody GetSchemaTable načíst informace o schématu aktuální sady výsledků. GetSchemaTable DataTable vrátí objekt naplněný řádky a sloupci, které obsahují informace o schématu pro aktuální sadu výsledků. DataTable obsahuje jeden řádek pro každý sloupec v sadě výsledků. Každý sloupec tabulky schématu se mapuje na vlastnost sloupců vrácených v řádcích sady výsledků, kde ColumnName je název vlastnosti a hodnota sloupce je hodnota vlastnosti. Následující příklad zapíše informace o schématu pro DataReader.

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

Práce s kapitolami OLE DB

Hierarchické sady řádků nebo kapitoly (typ OLE DB DBTYPE_HCHAPTER, adChapter typu ADO) lze načíst pomocí .OleDbDataReader Když se dotaz, který obsahuje kapitolu, vrátí jako DataReader, vrátí se kapitola jako sloupec v DataReader a je vystavena jako DataReader objekt.

DataSet ADO.NET lze také použít k reprezentaci hierarchických sad řádků pomocí relací nadřazených a podřízených mezi tabulkami. Další informace naleznete v tématu Datové sady, Datové tabulky a DataViews.

Následující příklad kódu používá zprostředkovatele MSDataShape k vygenerování sloupce objednávek pro každého zákazníka v seznamu zákazníka.

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

Vrácení výsledků pomocí Oracle REF CURSORs

Zprostředkovatel dat rozhraní .NET Framework pro Oracle podporuje použití Oracle REF CURSORs k vrácení výsledku dotazu. Oracle REF CURSOR je vrácen jako OracleDataReader.

Pomocí metody OracleDataReader můžete načíst objekt ExecuteReader, který reprezentuje Oracle REF CURSOR. Můžete také zadat OracleCommand, který vrátí jeden nebo více Oracle REF CURSORS jako SelectCommand pro OracleDataAdapter, který se používá k vyplnění DataSet.

Abyste získali přístup k REF CURSOR vráceného ze zdroje dat Oracle, vytvořte OracleCommand pro svůj dotaz a přidejte výstupní parametr, který odkazuje na REF CURSOR do Parameters kolekce vašeho OracleCommand. Název parametru se musí shodovat s názvem parametru REF CURSOR v dotazu. Nastavte typ parametru na OracleType.Cursor. Metoda OracleCommand.ExecuteReader() vašeho OracleCommand vrací OracleDataReader pro REF CURSOR.

Pokud váš OracleCommand vrací více REF CURSORS, přidejte více výstupních parametrů. K různým objektům REF CURSORs se dostanete voláním OracleCommand.ExecuteReader() metody. To volání ExecuteReader() vrátí OracleDataReader odkazující na první REF CURSOR. Poté můžete zavolat metodu OracleDataReader.NextResult() pro přístup k následným REF CURSORům. Přestože parametry v OracleCommand.Parameters kolekci odpovídají výstupním parametrům REF CURSOR podle názvu, OracleDataReader přistupuje k nim v pořadí, v jakém byly přidány do Parameters kolekce.

Představte si například následující balíček Oracle a text balíčku.

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;

Následující kód vytvoří OracleCommand, který vrátí REF CURSORs z předchozího balíčku Oracle tím, že do kolekce OracleType.Cursor přidá dva parametry typu OracleCommand.Parameters.

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;

Následující kód vrátí výsledky předchozího příkazu pomocí metod Read() a NextResult() z OracleDataReader. Parametry REF CURSOR se vrátí v pořadí.

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

Následující příklad používá předchozí příkaz k naplnění DataSet výsledků balíčku Oracle.

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

Poznámka:

Chcete-li zabránit OverflowException, doporučujeme, abyste před uložením hodnoty do DataRow zpracovali veškerý převod z typu Oracle NUMBER na platný typ rozhraní .NET Framework. Můžete použít událost FillError k určení, jestli došlo k OverflowException. Další informace o FillError události naleznete v tématu Zpracování událostí dataAdapter.

Viz také