Share via


Extraction de données à l'aide d'un DataReader (ADO.NET)

Mise à jour : November 2007

L'extraction de données à l'aide d'un DataReader implique la création d'une instance de l'objet Command, puis la création d'un DataReader en appelant Command.ExecuteReader pour extraire des lignes d'une source de données. Voici un exemple d'utilisation d'un DataReader où reader représente un DataReader valide et command représente un objet Command valide.

reader = command.ExecuteReader();

Vous utilisez la méthode Read de l'objet DataReader pour obtenir une ligne à partir des résultats de la requête. Vous pouvez accéder à chaque colonne de la ligne retournée en passant le nom ou la référence ordinale de la colonne au DataReader. Cependant, pour une meilleure performance, le DataReader fournit une série de méthodes qui vous permettent d'accéder aux valeurs de colonne dans leurs types de données natifs (GetDateTime, GetDouble, GetGuid, GetInt32, etc.). Pour obtenir une liste de méthodes d'accesseur typées pour les DataReaders spécifiques au fournisseur de données, voir les objets OleDbDataReader et SqlDataReader. L'utilisation des méthodes d'accesseur typées, lorsque le type de données sous-jacent est connu, réduit le volume de conversion de types requis lors de l'extraction de la valeur de colonne.

Remarque :

La version Windows Server 2003 du .NET Framework inclut une propriété supplémentaire pour le DataReader, HasRows, qui vous permet de déterminer si le DataReader a retourné des résultats avant d'y lire.

L'exemple de code suivant itère dans un objet DataReader et retourne deux colonnes à partir de chaque ligne.

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
static void HasRows(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "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();
    }
}

Le DataReader fournit un flux de données non mis en tampon qui permet à la logique procédurale de traiter efficacement les résultats provenant d'une source de données de façon séquentielle. Le DataReader se révèle être un bon choix lors de l'extraction de grandes quantités de données car celles-ci ne sont pas mises en cache dans la mémoire.

Fermeture du DataReader

Vous devez toujours appeler la méthode Close lorsque vous avez fini d'utiliser l'objet DataReader.

Si Command contient des paramètres de sortie ou des valeurs de retour, ils ne seront pas disponibles avant la fermeture du DataReader.

Notez que pendant l'ouverture d'un DataReader, Connection est utilisé en mode exclusif par ce DataReader. Vous ne pouvez pas exécuter de commandes pour Connection, y compris la création d'un autre DataReader, jusqu'à la fermeture du DataReader d'origine.

Remarque :

N'appelez pas Close ou Dispose sur un objet Connection, DataReader ou tout autre objet managé dans la méthode Finalize de votre classe. Dans un finaliseur, libérez seulement les ressources non managées que votre classe possède directement. Si votre classe ne possède pas de ressources non managées, n'incluez pas la méthode Finalize dans votre définition de classe. Pour plus d'informations, voir Garbage collection.

Extraction de plusieurs jeux de résultats à l'aide de NextResult

Si des jeux de résultats multiples sont retournés, le DataReader fournit la méthode NextResult pour itérer sur les jeux de résultats dans l'ordre. L'exemple suivant montre l'objet SqlDataReader traitant les résultats de deux instructions SELECT utilisant la méthode ExecuteReader.

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
static void RetrieveMultipleResults(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "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();
        }
    }
}

Obtention d'informations de schéma à partir du DataReader

Lorsqu'un DataReader est ouvert, vous pouvez extraire des informations de schéma concernant le jeu de résultats actuel à l'aide de la méthode GetSchemaTable. GetSchemaTable retourne un objet DataTable rempli de lignes et de colonnes qui contiennent les informations de schéma pour le jeu de résultats actuel. Le DataTable contient une ligne pour chaque colonne du jeu de résultats. Chaque colonne de la ligne de table de schéma mappe à une propriété de la colonne retournée dans le jeu de résultats, où ColumnName est le nom de la propriété et la valeur de la colonne est la valeur de la propriété. L'exemple de code suivant écrit les informations de schéma pour DataReader.

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
static void GetSchemaInfo(SqlConnection connection)
{
    using (connection)
    {
        SqlCommand command = new SqlCommand(
          "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]));
            }
        }
    }
}

Utilisation de chapitres OLE DB

Les jeux de lignes hiérarchiques ou chapitres (DBTYPE_HCHAPTER de type OLE DB, adChapter de type ADO) peuvent être extraits à l'aide de l'objet OleDbDataReader. Lorsqu'une requête comprenant un chapitre est retournée comme DataReader, le chapitre est retourné comme colonne dans ce DataReader et exposé comme objet DataReader.

Le DataSet ADO.NET peut aussi être utilisé pour représenter des jeux de lignes hiérarchiques à l'aide de relations parent-enfant entre les tables. Pour plus d'informations, voir Objets DataSet, DataTable et DataView (ADO.NET).

L'exemple de code suivant utilise le fournisseur MSDataShape pour générer une colonne chapitre de commandes pour chaque client d'une liste de clients.

Using connection As OleDbConnection = New OleDbConnection( _
  "Provider=MSDataShape;Data Provider=SQLOLEDB;" & _
  "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")

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

Dim custReader As OleDbDataReader = custCMD.ExecuteReader()
Dim orderReader As OleDbDataReader

Do While custReader.Read()
  Console.WriteLine("Orders for " & custReader.GetString(1)) 
  ' custReader.GetString(1) = CompanyName

  orderReader = 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()
Loop
' Make sure to always close readers and connections.
custReader.Close()
End Using
Using (OleDbConnection connection = new OleDbConnection(
  "Provider=MSDataShape;Data Provider=SQLOLEDB;" +
  "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"));
{
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();

OleDbDataReader custReader = custCMD.ExecuteReader();
OleDbDataReader orderReader;

while (custReader.Read())
{
  Console.WriteLine("Orders for " + custReader.GetString(1)); 
  // custReader.GetString(1) = CompanyName

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

Retour de résultats avec des REF CURSOR Oracle

Le fournisseur de données .NET Framework pour Oracle prend en charge l'utilisation des REF CURSOR Oracle pour retourner le résultat d'une requête. Un REF CURSOR Oracle est retourné en tant qu'objet OracleDataReader.

Vous pouvez extraire un objet OracleDataReader qui représente un REF CURSOR Oracle à l'aide de la méthode ExecuteReader et également spécifier un objet OracleCommand qui retourne un ou plusieurs REF CURSOR Oracle en tant que SelectCommand d'un objet OracleDataAdapter utilisé pour remplir un objet DataSet.

Pour accéder à un REF CURSOR retourné par une source de données Oracle, créez un OracleCommand pour votre requête et ajoutez un paramètre de sortie qui référence le REF CURSOR à la collection Parameters de votre OracleCommand. Le nom du paramètre doit correspondre à celui du paramètre REF CURSOR de votre requête. Définissez OracleType.Cursor comme type de paramètre. La méthode ExecuteReader de votre OracleCommand retourne un OracleDataReader pour REF CURSOR.

Si votre OracleCommand retourne plusieurs REF CURSOR, ajoutez plusieurs paramètres de sortie. Vous pouvez accéder aux différents REF CURSOR en appelant la méthode OracleCommand.ExecuteReader. L'appel à la méthode ExecuteReader retourne un OracleDataReader qui référence le premier REF CURSOR. Vous pouvez ensuite appeler la méthode OracleDataReader.NextResult pour accéder aux REF CURSOR suivants. Bien que les paramètres de votre collection OracleCommand.Parameters coïncident par leur nom avec les paramètres de sortie du REF CURSOR, le OracleDataReader y accède selon l'ordre de leur ajout à la collection Parameters.

Considérez, par exemple, le package et le corps de package Oracle suivants.

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; 

Le code suivant crée un OracleCommand qui retourne les REF CURSOR d'un précédent package Oracle en ajoutant deux paramètres de type OracleType.Cursor à la collection 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;

Le code suivant retourne les résultats de la précédente commande à l'aide des méthodes Read et NextResult de OracleDataReader. Les paramètres REF CURSOR sont retournés dans l'ordre.

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

L'exemple suivant utilise la commande précédente pour remplir un DataSet avec les résultats du package Oracle.

Remarque :

Pour éviter une OverflowException, nous vous recommandons également d'opérer toute conversion du type Oracle NUMBER en un type .NET Framework valide avant de stocker la valeur dans un DataRow. Vous pouvez utiliser l'événement FillError pour déterminer si une exception OverflowException s'est produite. Pour plus d'informations sur l'événement FillError, voir Gestion des événements DataAdapter (ADO.NET).

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

Voir aussi

Autres ressources

DataReaders (ADO.NET)

DataAdapters et DataReaders (ADO.NET)

Commandes et paramètres (ADO.NET)

Récupération d'informations de schéma de base de données (ADO.NET)