Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Чтобы получить данные с помощью 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".