Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Para recuperar dados usando um DataReader, crie uma instância do Command objeto e depois crie um DataReader chamando Command.ExecuteReader para recuperar linhas de uma fonte de dados. O DataReader fornece um fluxo de dados não bufferizado que permite à lógica procedural processar os resultados de uma fonte de dados de forma eficiente e sequencialmente. O DataReader é uma boa escolha quando se está a recuperar grandes quantidades de dados porque os dados não estão armazenados em cache na memória.
O exemplo a seguir ilustra o uso de um DataReader, onde reader representa um DataReader válido e command representa um objeto Command válido.
reader = command.ExecuteReader();
reader = command.ExecuteReader()
Use o método DataReader.Read para obter uma linha dos resultados da consulta. Você pode acessar cada coluna da linha retornada passando o nome ou o número ordinal da coluna para o DataReader. No entanto, para melhor desempenho, fornece DataReader uma série de métodos que permitem aceder aos valores das colunas nos seus tipos de dados nativos (GetDateTime, GetDouble, GetGuid, GetInt32, entre outros). Para obter uma lista de métodos de acesso tipados para DataReaders específicos do provedor de dados, consulte OleDbDataReader e SqlDataReader. Usar os métodos de acesso tipados quando se conhece o tipo de dados subjacente reduz a quantidade de conversão de tipo necessária ao recuperar o valor da coluna.
O exemplo seguinte itera através de um DataReader objeto e devolve duas colunas de cada linha.
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
Encerramento do DataReader
Chame sempre o Close método quando terminar de usar o DataReader objeto.
Se o Command seu contém parâmetros de saída ou valores de retorno, esses valores não estão disponíveis até que o DataReader esteja fechado.
Enquanto a DataReader estiver aberto, o Connection é usado exclusivamente por esse DataReader. Não pode executar quaisquer comandos para a Ligação, incluindo criar outro Leitor de Dados, até que o original DataReader esteja fechado.
Observação
Não ligue Close nem Dispose em uma Ligação, um DataReader ou qualquer outro objeto gerido no método da sua classe. Em um finalizador, libere apenas recursos não gerenciados que sua classe possui diretamente. Se a sua turma não possui recursos não geridos, não inclua nenhum Finalize método na definição da sua classe. Para obter mais informações, consulte Coleta de lixo.
Recuperando vários conjuntos de resultados usando NextResult
Se o DataReader devolver múltiplos conjuntos de resultados, chamar o método NextResult para iterar sequencialmente pelos conjuntos de resultados. O exemplo a seguir mostra o SqlDataReader processamento dos resultados de duas instruções SELECT usando o ExecuteReader método.
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
Obtendo informações de esquema do DataReader
Enquanto um DataReader estiver aberto, pode obter informações sobre o esquema do conjunto de resultados atual usando o método GetSchemaTable.
GetSchemaTable devolve um DataTable objeto preenchido com linhas e colunas que contêm a informação do esquema para o conjunto de resultados atual. O DataTable contém uma linha para cada coluna do conjunto de resultados. Cada coluna da tabela de esquema corresponde a uma propriedade das colunas retornadas nas linhas do conjunto de resultados, em que o ColumnName é o nome da propriedade e o valor da coluna é o valor da propriedade. O exemplo a seguir escreve as informações de esquema para 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
Trabalhando com capítulos do OLE DB
Conjuntos de linhas hierárquicos, ou capítulos (OLE DB tipo DBTYPE_HCHAPTER, tipo ADO adChapter), podem ser recuperados usando o OleDbDataReader. Quando uma consulta que inclui um capítulo é devolvida como DataReader, o capítulo é devolvido como uma coluna nesse DataReader e é exposto como um DataReader objeto.
A ADO.NET DataSet também pode ser usada para representar conjuntos de linhas hierárquicas usando relações pai-filho entre tabelas. Para obter mais informações, consulte DataSets, DataTables e DataViews.
O exemplo de código a seguir usa o provedor MSDataShape para gerar uma coluna de capítulo de pedidos para cada cliente em uma lista de clientes.
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();
}
}
}
Retornar resultados com Oracle REF CURSORs
O .NET Framework Data Provider for Oracle suporta o uso de Oracle REF CURSORs para retornar um resultado de consulta. Um Oracle REF CURSOR é retornado como um OracleDataReader.
Você pode recuperar um OracleDataReader objeto que representa um Oracle REF CURSOR usando o ExecuteReader método. Também pode especificar um OracleCommand que devolve um ou mais CURSORs Oracle REF como o SelectCommand para um OracleDataAdapter usado para preencher um DataSet.
Para acessar um REF CURSOR retornado de uma fonte de dados Oracle, crie um OracleCommand para sua consulta e adicione um parâmetro de saída que faça referência ao REF CURSOR à Parameters coleção do seu OracleCommand. O nome do parâmetro deve corresponder ao nome do parâmetro REF CURSOR na consulta. Defina o tipo do parâmetro como OracleType.Cursor. O OracleCommand.ExecuteReader() método do seu OracleCommand retorna um OracleDataReader para o REF CURSOR.
Se o seu OracleCommand retornar vários REF CURSORS, adicione vários Parâmetros de Saída. Você pode acessar os diferentes CURSORs REF chamando o OracleCommand.ExecuteReader() método. A chamada para ExecuteReader() retorna um OracleDataReader que referencia o primeiro REF CURSOR. Em seguida, você pode chamar o OracleDataReader.NextResult() método para acessar REF CURSORs subsequentes. Embora os parâmetros em sua OracleCommand.Parameters coleção correspondam aos parâmetros de saída REF CURSOR por nome, o OracleDataReader acessa-os na ordem em que foram adicionados à Parameters coleção.
Por exemplo, considere o seguinte pacote Oracle e corpo do pacote.
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;
O código a seguir cria um OracleCommand que retorna os CURSORs REF do pacote Oracle anterior adicionando dois parâmetros do tipo OracleType.Cursor à OracleCommand.Parameters coleção.
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;
O código a seguir retorna os resultados do comando anterior usando os Read() métodos e NextResult() do OracleDataReader. Os parâmetros REF CURSOR são retornados em ordem.
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();
O exemplo a seguir usa o comando anterior para preencher um DataSet com os resultados do pacote 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);
Observação
Para evitar um OverflowException, recomendamos que você também manipule qualquer conversão do tipo Oracle NUMBER para um tipo .NET Framework válido antes de armazenar o valor em um DataRowarquivo . Pode usar o FillError evento para determinar se algo OverflowException ocorreu. Para obter mais informações sobre o FillError evento, consulte Manipulando eventos DataAdapter.