Partager via


Récupérer des données à l’aide d’un DataReader

Pour récupérer des données à l’aide d’un DataReader, créez une instance de l’objet Command , puis créez-en DataReader un en appelant Command.ExecuteReader pour récupérer des lignes à partir d’une source de données. Le DataReader fournit un flux de données non mis en mémoire tampon qui permet à une logique procédurale de traiter efficacement les résultats d'une source de données de manière séquentielle. Le DataReader est un bon choix lorsque vous récupérez de grandes quantités de données, car les données ne sont pas mises en cache en mémoire.

Voici un exemple d’utilisation d’un DataReaderreader représente un DataReader valide et où command représente un objet Command valide.

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

Utilisez la méthode DataReader.Read pour obtenir une ligne 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. Toutefois, pour des performances optimales, les DataReader méthodes fournissent 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, consultez OleDbDataReader et SqlDataReader. L’utilisation des méthodes d’accesseur typées quand vous connaissez le type de données sous-jacent réduit la quantité des conversions de type nécessaires lors de l’extraction de la valeur de colonne.

L’exemple suivant itère à travers un objet DataReader et retourne deux colonnes de chaque rangée.

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

Fermeture de DataReader

Appelez toujours la Close méthode lorsque vous avez terminé d’utiliser l’objet DataReader .

Si votre Command fichier contient des paramètres de sortie ou des valeurs de retour, ces valeurs ne sont pas disponibles tant que celles-ci DataReader ne sont pas fermées.

Bien qu’un DataReader soit ouvert, un Connection est utilisé exclusivement par ce DataReader. Vous ne pouvez pas exécuter de commandes pour la connexion, y compris la création d’un autre DataReader, jusqu’à ce que l’original DataReader soit fermé.

Remarque

N'appelez pas Close ou Dispose sur une connexion, un DataReader, ou tout autre objet géré 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 aucune ressource non managée, n’incluez pas de Finalize méthode dans votre définition de classe. Pour plus d’informations, consultez Nettoyage de la mémoire.

Récupération de plusieurs jeux de résultats à l’aide de NextResult

Si le DataReader résultat retourne plusieurs jeux de résultats, appelez la NextResult méthode pour itérer dans les jeux de résultats de manière séquentielle. L'exemple suivant montre l'objet SqlDataReader traitant les résultats de deux instructions SELECT utilisant la méthode 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

Obtention d’informations de schéma à partir de DataReader

Lorsqu'un DataReader est ouvert, vous pouvez obtenir des informations de schéma sur le jeu de résultats actuel en utilisant la méthode GetSchemaTable. GetSchemaTable retourne un DataTable objet 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 table de schéma est associée à une propriété des colonnes renvoyées dans les lignes du 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.

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

Travail avec les chapitres OLE DB

Les ensembles de lignes hiérarchiques ou les chapitres (type OLE DB DBTYPE_HCHAPTER, adChapter de type ADO) peuvent être récupérés à l’aide du OleDbDataReader. Lorsqu’une requête qui inclut un chapitre est retournée en tant que DataReader, le chapitre est retourné sous la forme d’une colonne dans ce DataReader chapitre et est exposé en tant qu’objet DataReader .

Le ADO.NET DataSet peut également être utilisé pour représenter des ensembles de lignes hiérarchiques à l’aide de relations parent-enfant entre les tables. Pour plus d’informations, consultez DataSets, DataTables et DataViews.

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

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

Retour de résultats avec des REF CURSORS Oracle

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

Vous pouvez récupérer un OracleDataReader objet qui représente un CURSEUR REF Oracle à l’aide de la ExecuteReader méthode. Vous pouvez également spécifier un OracleCommand qui retourne un ou plusieurs CURSORs Oracle REF comme SelectCommand pour un OracleDataAdapter utilisé pour remplir un DataSet.

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

Si votre OracleCommand renvoie plusieurs curseurs REF, ajoutez plusieurs paramètres de sortie. Vous pouvez accéder aux différents REF CURSORs en appelant la OracleCommand.ExecuteReader() méthode. L’appel à 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 CURSORS suivants. Bien que les paramètres de la collection OracleCommand.Parameters correspondent par nom aux paramètres de sortie REF CURSOR, ils sont accédés par les OracleDataReader dans l'ordre où ils ont été ajoutés à 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 CURSORs du package Oracle précédent en ajoutant deux paramètres de type OracleType.Cursor à la OracleCommand.Parameters collection.

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 commande précédente à l’aide des méthodes Read() et NextResult() du 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.

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

Remarque

Pour éviter un OverflowException, nous vous recommandons de gérer également toute conversion du type Oracle NUMBER vers un type .NET Framework valide avant de stocker la valeur dans un DataRow. Vous pouvez utiliser l’événement FillError pour déterminer si un OverflowException événement s’est produit. Pour plus d’informations sur l’événement FillError , consultez Gestion des événements DataAdapter.

Voir aussi