Share via


Mengambil data menggunakan DataReader

Untuk mengambil data menggunakan DataReader, buat instans objek Perintah, lalu buat DataReader dengan memanggil Command.ExecuteReader ke mengambil baris dari sumber data. DataReader menyediakan aliran data yang tidak di-buffer yang memungkinkan logika prosedural memproses hasil secara efisien dari sumber data secara berurutan. DataReader adalah pilihan yang baik saat Anda mengambil data dalam jumlah besar karena data tidak disimpan dalam cache di memori.

Contoh berikut mengilustrasikan penggunaan DataReader, di mana reader mewakili DataReader yang valid dan command mewakili objek Perintah yang valid.

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

Gunakan metode DataReader.Read untuk mendapatkan baris dari hasil kueri. Anda dapat mengakses setiap kolom dari baris yang dikembalikan dengan meneruskan nama atau nomor urut kolom ke DataReader. Namun, untuk mendapatkan performa terbaik, DataReader menyediakan serangkaian metode yang memungkinkan Anda mengakses nilai kolom dalam jenis data aslinya (GetDateTime, GetDouble, GetGuid, GetInt32, dan seterusnya). Untuk daftar metode pengakses yang diketik untuk DataReaders khusus penyedia data, lihat OleDbDataReader dan SqlDataReader. Menggunakan metode pengakses yang diketik saat Anda mengetahui jenis data yang mendasarinya mengurangi jumlah konversi jenis yang diperlukan saat mengambil nilai kolom.

Contoh berikut mengulangi melalui objek DataReader dan mengembalikan dua kolom dari setiap baris.

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

Menutup DataReader

Selalu panggil metode Tutup setelah Anda selesai menggunakan objek DataReader.

Jika Perintah Anda berisi parameter output atau nilai kembalian, nilai tersebut tidak tersedia hingga DataReader ditutup.

Saat DataReader terbuka, Koneksi digunakan secara eksklusif oleh DataReader tersebut. Anda tidak dapat menjalankan perintah apa pun untuk Koneksi, termasuk membuat DataReader lain, hingga DataReader asli ditutup.

Catatan

Jangan panggil Tutup atau Buang pada Koneksi, DataReader, atau objek terkelola lainnya di metode Selesaikan kelas Anda. Di penyelesai, hanya merilis sumber daya yang tidak dikelola yang kelas Anda miliki secara langsung. Jika kelas Anda tidak memiliki sumber daya yang tidak dikelola, jangan sertakan metode Selesaikan dalam definisi kelas Anda. Untuk informasi selengkapnya, lihat Pengumpulan Sampah.

Mengambil beberapa set hasil menggunakan NextResult

Jika DataReader mengembalikan beberapa kumpulan hasil, panggil metode NextResult untuk mengulangi kumpulan hasil secara berurutan. Contoh berikut menunjukkan SqlDataReader memproses hasil dua pernyataan SELECT menggunakan metode 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{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

Mendapatkan informasi skema dari DataReader

Saat DataReader terbuka, Anda dapat mengambil informasi skema tentang kumpulan hasil saat ini menggunakan metode GetSchemaTable. GetSchemaTable mengembalikan objek DataTable yang diisi dengan baris dan kolom yang berisi informasi skema untuk kumpulan hasil saat ini. DataTable berisi satu baris untuk setiap kolom kumpulan hasil. Setiap kolom tabel skema dipetakan ke properti kolom yang dikembalikan dalam baris kumpulan hasil, di mana ColumnName adalah nama properti dan nilai kolom adalah nilai properti. Contoh berikut menuliskan informasi skema untuk 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

Bekerja dengan bab OLE DB

Baris atau bab hierarkis (jenis OLE DB DBTYPE_HCHAPTER, jenis ADO adChapter), dapat diambil menggunakan OleDbDataReader. Saat kueri yang menyertakan bab dikembalikan sebagai DataReader, bab dikembalikan sebagai kolom di DataReader tersebut dan diekspos sebagai objek DataReader.

DataSet ADO.NET juga dapat digunakan untuk mewakili kumpulan baris hierarkis dengan menggunakan hubungan induk-turunan antar tabel. Untuk informasi selengkapnya, lihat DataSets, DataTables, dan DataViews.

Contoh kode berikut menggunakan Penyedia MSDataShape guna menghasilkan kolom bab pesanan untuk setiap pelanggan dalam daftar pelanggan.

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

Mengembalikan hasil dengan Oracle REF CURSORs

Penyedia Data .NET Framework untuk Oracle mendukung penggunaan Oracle REF CURSOR untuk mengembalikan hasil kueri. KURSOR REF Oracle dikembalikan sebagai OracleDataReader.

Anda dapat mengambil objek OracleDataReader yang mewakili Oracle REF CURSOR dengan menggunakan metode ExecuteReader. Anda juga dapat menentukan OracleCommand yang mengembalikan satu atau lebih Oracle REF CURSOR sebagai SelectCommand untuk OracleDataAdapter yang digunakan untuk mengisi DataSet.

Untuk mengakses KURSOR REF yang dikembalikan dari sumber data Oracle, buat OracleCommand untuk kueri Anda dan tambahkan parameter output yang mereferensikan KURSOR REF ke kumpulan ParametersOracleCommand Anda. Nama parameter harus cocok dengan nama parameter REF CURSOR dalam kueri Anda. Atur jenis parameter ke OracleType.Cursor. Metode OracleCommand.ExecuteReader() dari OracleCommand Anda mengembalikan OracleDataReader untuk KURSOR REF.

Jika OracleCommand Anda mengembalikan beberapa KURSOR REF, tambahkan beberapa parameter output. Anda dapat mengakses KURSOR REF yang berbeda dengan memanggil metode OracleCommand.ExecuteReader(). Panggilan ke ExecuteReader() mengembalikan OracleDataReader yang merujuk pada KURSOR REF pertama. Anda kemudian dapat memanggil metode OracleDataReader.NextResult() untuk mengakses KURSOR REF berikutnya. Meskipun parameter dalam kumpulan OracleCommand.Parameters Anda cocok dengan parameter output REF CURSOR berdasarkan nama, OracleDataReader mengaksesnya sesuai urutan penambahannya ke kumpulan Parameters.

Misalnya, pertimbangkan paket Oracle dan isi paket berikut.

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;

Kode berikut membuat OracleCommand yang mengembalikan KURSOR REF dari paket Oracle sebelumnya dengan menambahkan dua parameter jenis OracleType.Cursor ke kumpulan 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;  

Kode berikut mengembalikan hasil dari perintah sebelumnya menggunakan metode Read() dan NextResult() dari OracleDataReader. Parameter KURSOR REF dikembalikan secara berurutan.

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

Contoh berikut menggunakan perintah sebelumnya untuk mengisi DataSet dengan hasil paket 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);  

Catatan

Untuk menghindari OverflowException, sebaiknya Anda juga menangani konversi apa pun dari jenis Oracle NUMBER ke jenis .NET Framework yang valid sebelum menyimpan nilai dalam DataRow. Anda dapat menggunakan peristiwa FillError untuk menentukan apakah OverflowException telah terjadi. Untuk informasi selengkapnya tentang peristiwa FillError, lihat Menangani Peristiwa DataAdapter.

Lihat juga