Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
Чтобы получить данные с помощью DataReader, создайте экземпляр Command объекта, а затем создайте его DataReader , вызвав Command.ExecuteReader для получения строк из источника данных.
DataReader предоставляет небуферизованный поток данных, что позволяет процедурной логике эффективно обрабатывать результаты из источника данных последовательно.
DataReader — это хороший выбор при извлечении больших объемов данных, поскольку данные не сохраняются в кэше памяти.
В следующем примере показано использование DataReader, где представляет допустимый reader и command представляет допустимый объект Command.
reader = command.ExecuteReader();
reader = command.ExecuteReader()
Используйте метод DataReader.Read , чтобы получить строку из результатов запроса. Вы можете получить доступ к каждому столбцу возвращаемой строки, передав имя или порядковый номер столбца в DataReader. Однако для повышения производительности DataReader предоставляет ряд методов, позволяющих получить доступ к значениям столбцов в собственных типах данных (GetDateTime, GetDouble, GetGuid, GetInt32 и т. д.). Список типизированных методов доступа для конкретного поставщика данных DataReaders см. в разделе OleDbDataReader и SqlDataReader. Использование методов типизированного доступа, когда известен базовый тип данных, уменьшает количество операций по преобразованию типов, необходимых при получении значения столбца.
В следующем примере выполняется итерация по объекту DataReader и возвращается два столбца из каждой строки.
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
Закрытие DataReader
Всегда вызывайте Close метод после завершения использования DataReader объекта.
Если в вашем Command содержатся выходные параметры или возвращаемые значения, то они остаются недоступными до закрытия DataReader.
Хотя объект DataReader открыт, Connection используется исключительно этим DataReader. Вы не можете выполнить какие-либо команды для подключения, включая создание другого DataReader, пока исходный файл DataReader не будет закрыт.
Замечание
Не вызывайте Finalize метод в определение класса. Дополнительные сведения см. в статье Сборка мусора.
Получение нескольких результирующих наборов с помощью NextResult
Если DataReader возвращает несколько результирующих наборов, вызовите метод NextResult для последовательной итерации через эти наборы. В следующем примере показана SqlDataReader обработка результатов двух инструкций SELECT с помощью 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
Получение сведений о схеме из DataReader
DataReader Когда он открыт, вы можете получить сведения о схеме текущего результирующего набора с помощью метода GetSchemaTable.
GetSchemaTable
DataTable возвращает объект, заполненный строками и столбцами, содержащими сведения о схеме для текущего результирующего набора.
DataTable содержит одну строку на каждый столбец результирующего набора. Каждый столбец таблицы схемы сопоставляется со свойством столбцов, возвращаемых в строках результирующего набора, где ColumnName имя свойства, а значение столбца — значение свойства. В следующем примере выписываются сведения о схеме для 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
Работа с разделами OLE DB
Иерархические наборы строк или главы (тип OLE DB DBTYPE_HCHAPTER, тип ADO adChapter), можно получить с помощью .OleDbDataReader Когда запрос, содержащий главу, возвращается в виде DataReader, глава возвращается в качестве столбца в этом DataReader и предоставляется в качестве DataReader объекта.
Кроме того, ADO.NET DataSet можно использовать для представления иерархических наборов строк с помощью родительско-дочерних связей между таблицами. Дополнительные сведения см. в разделе DataSets, DataTables и DataViews.
В следующем примере кода для создания столбца заказов для каждого клиента в списке клиентов используется поставщик MSDataShape Provider.
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();
}
}
}
Возврат результатов с помощью Oracle REF CURSORs
Поставщик данных .NET Framework для Oracle поддерживает использование oracle REF CURSORs для возврата результата запроса. Курсор Oracle REF возвращается в виде OracleDataReader.
Вы можете получить объект, представляющий Oracle REF CURSOR, с помощью метода OracleDataReaderExecuteReader. Можно также указать OracleCommand, который возвращает один или несколько Oracle REF CURSOR в качестве SelectCommand для OracleDataAdapter, используемого для заполнения DataSet.
Чтобы получить доступ к REF CURSOR, возвращенному из источника данных Oracle, создайте OracleCommand для вашего запроса и добавьте выходной параметр, который ссылается на REF CURSOR, в коллекцию Parameters вашего OracleCommand. Имя параметра должно соответствовать имени параметра REF CURSOR в запросе. Задайте для параметра тип OracleType.Cursor. Метод OracleCommand.ExecuteReader() вашего OracleCommand возвращает OracleDataReader для REF CURSOR.
Если ваш OracleCommand возвращает несколько курсоров REF, добавьте соответствующие выходные параметры. Вы можете получить доступ к различным REF CURSOR, вызвав метод OracleCommand.ExecuteReader(). Вызов ExecuteReader() возвращает объект OracleDataReader, ссылающийся на первый REF CURSOR. Затем можно вызвать метод OracleDataReader.NextResult(), чтобы получить доступ к последующим курсорам REF. Хотя параметры в вашей коллекции OracleCommand.Parameters совпадают по имени с выходными параметрами REF CURSOR, OracleDataReader обращается к ним в том порядке, в котором они были добавлены в коллекцию Parameters.
Например, рассмотрим следующий пакет Oracle и его тело.
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;
Следующий код создает объект OracleCommand , который возвращает REF CURSORs из предыдущего пакета Oracle, добавив два параметра типа OracleType.Cursor в коллекцию 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;
Следующий код возвращает результаты предыдущей команды, используя методы Read() и NextResult() из OracleDataReader. Параметры REF CURSOR возвращаются в порядке следования.
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();
В следующем примере предыдущая команда используется для заполнения DataSet данными из пакета 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);
Замечание
Чтобы избежать OverflowException, рекомендуется также выполнять обработку всех преобразований из типа Oracle NUMBER в допустимый тип .NET Framework перед сохранением значения в DataRow. Событие FillError можно использовать для определения, произошло ли OverflowException. Дополнительные сведения о событии FillError см. в разделе "Обработка событий DataAdapter".