Mettre à jour une base de données SQL Server à l’aide de l’objet SqlDataAdapter dans Visual C++

Cet article explique comment utiliser l’objet SqlDataAdapter pour mettre à jour une base de données SQL Server dans Microsoft Visual C++.

Version d’origine du produit : Visual C++
Numéro de la base de connaissances d’origine : 308510

Résumé

L’objet SqlDataAdapter sert de pont entre un objet ADO.NET DataSet et une base de données SQL Server. Il s’agit d’un objet intermédiaire que vous pouvez utiliser pour effectuer les opérations suivantes :

  • Remplissez un ADO.NET DataSet avec des données récupérées à partir d’une base de données SQL Server.
  • Mettez à jour la base de données pour refléter les modifications (insertions, mises à jour, suppressions) apportées aux données à l’aide de DataSet. Cet article fournit des exemples de code Visual C++ .NET pour montrer comment l’objet SqlDataAdapter peut être utilisé pour mettre à jour une base de données SQL Server avec des modifications de données exécutées sur un DataSet objet qui est rempli avec les données d’une table dans la base de données.

Cet article fait référence à l’espace de noms System::Data::SqlClientde la bibliothèque de classes .NET Framework .

Propriétés et objet SqlDataAdapter

Les InsertCommandpropriétés , UpdateCommandet DeleteCommand de l’objet SqlDataAdapter sont utilisées pour mettre à jour la base de données avec les modifications de données exécutées sur un DataSet objet . Chacune de ces propriétés est SqlCommand des objets qui spécifient les commandes , et DELETE TSQL respectives INSERTUPDATEutilisées pour publier les DataSet modifications apportées à la base de données cible. Les SqlCommand objets affectés à ces propriétés peuvent être créés manuellement dans le code ou peuvent être générés automatiquement à l’aide de l’objet SqlCommandBuilder .

Le premier exemple de code de cet article montre comment l’objet SqlCommandBuilder peut être utilisé pour générer automatiquement la UpdateCommand propriété de l’objet SqlDataAdapter . Le deuxième exemple utilise un scénario dans lequel la UpdateCommand génération automatique de commandes ne peut pas être utilisée et illustre donc le processus par lequel vous pouvez créer et utiliser manuellement un SqlCommand objet comme propriété d’un SqlDataAdapter objet.

Créer l’exemple de table SQL Server

Pour créer un exemple de table SQL Server à utiliser dans les exemples de code Visual C++ .NET documentés dans cet article, procédez comme suit :

  1. Ouvrez SQL Server Analyseur de requête, puis connectez-vous à une base de données dans laquelle vous souhaitez créer l’exemple de table. Les exemples de code de cet article utilisent la base de données Northwind fournie avec SQL Server.

  2. Exécutez les instructions T-SQL suivantes pour créer un exemple de table appelé CustTest, puis insérez-y un enregistrement.

    Create Table CustTest
    (
        CustID int primary key,
        CustName varchar(20)
    )
    Insert into CustTest values(1,'John')
    

Exemple de code 1 : commandes générées automatiquement

Si l’instruction SELECT permettant de récupérer les données utilisées pour remplir un DataSet est basée sur une table de base de données unique, vous pouvez tirer parti de l’objet CommandBuilder pour générer automatiquement les DeleteCommandpropriétés , InsertCommandet UpdateCommand du DataAdapter. Cela simplifie et réduit le code requis pour effectuer INSERTles opérations , UPDATEet DELETE .

Au minimum, vous devez définir la propriété pour que la SelectCommand génération automatique de commandes fonctionne. Le schéma de table récupéré par détermine SelectCommand la syntaxe des instructions , UPDATEet DELETE générées INSERTautomatiquement.

doit SelectCommand également retourner au moins une clé primaire ou une colonne unique. Si aucune n’est présente, une InvalidOperation exception est générée et les commandes ne sont pas générées.

Pour créer un exemple d’application console Visual C++ .NET qui montre comment utiliser l’objet SqlCommandBuilder afin de générer automatiquement les InsertCommandpropriétés d’objet , DeleteCommandet UpdateCommand SqlCommand pour un SqlDataAdapter objet, procédez comme suit :

  1. Démarrez Visual Studio .NET, puis créez une application C++ managée. Nommez-le updateSQL.

  2. Copiez et collez le code suivant dans updateSQL.cpp (en remplaçant son contenu par défaut) :

    #include "stdafx.h"
    
    #using < mscorlib.dll>
    #using < System.dll>
    #using < System.Data.dll>
    #using < System.Xml.dll>
    
    using namespace System;
    using namespace System::Data;
    using namespace System::Data::SqlClient;
    
    #ifdef _UNICODE
        int wmain(void)
    #else
        int main(void)
    #endif
    {
        SqlConnection *cn = new SqlConnection();
        DataSet *CustomersDataSet = new DataSet();
        SqlDataAdapter *da;
        SqlCommandBuilder *cmdBuilder;
    
        //Set the connection string of the SqlConnection object to connect
        //to the SQL Server database in which you created the sample
        //table in Section 1.0
        cn->ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
        cn->Open();
    
        //Initialize the SqlDataAdapter object by specifying a Select command
        //that retrieves data from the sample table
        da = new SqlDataAdapter("select * from CustTest order by CustId", cn);
    
        //Initialize the SqlCommandBuilder object to automatically generate and initialize
        //the UpdateCommand, InsertCommand and DeleteCommand properties of the SqlDataAdapter
        cmdBuilder = new SqlCommandBuilder(da);
    
        //Populate the DataSet by executing the Fill method of the SqlDataAdapter
        da->Fill(CustomersDataSet, "Customers");
    
        //Display the Update, Insert and Delete commands that were automatically generated
        //by the SqlCommandBuilder object
        Console::WriteLine("Update command Generated by the Command Builder : ");
        Console::WriteLine("==================================================");
        Console::WriteLine(cmdBuilder->GetUpdateCommand()->CommandText);
        Console::WriteLine(" ");
        Console::WriteLine("Insert command Generated by the Command Builder : ");
        Console::WriteLine("==================================================");
        Console::WriteLine(cmdBuilder->GetInsertCommand()->CommandText);
        Console::WriteLine(" ");
        Console::WriteLine("Delete command Generated by the Command Builder : ");
        Console::WriteLine("==================================================");
        Console::WriteLine(cmdBuilder->GetDeleteCommand()->CommandText);
        Console::WriteLine(" ");
    
        //Write out the value in the CustName field before updating the data using the DataSet
        DataRow *rowCust = CustomersDataSet->Tables->Item["Customers"]->Rows->Item[0];
        Console::WriteLine("Customer Name before Update : {0} ", rowCust->Item["CustName"]);
    
        //Modify the value of the CustName field
        String *newStrVal = new String("Jack");
        rowCust->set_Item("CustName", newStrVal);
    
        //Modify the value of the CustName field again
        String *newStrVal2 = new String("Jack2");
        rowCust->set_Item("CustName", newStrVal2);
    
        //Post the data modification to the database
        da->Update(CustomersDataSet, "Customers");
    
        Console::WriteLine("Customer Name after Update : {0} ", rowCust->Item["CustName"]);
    
        //Close the database connection
        cn->Close();
    
        //Pause
        Console::ReadLine();
        return 0;
    }
    
  3. Dans le code que vous avez copié et collé à l’étape 2, modifiez la ligne du code de chaîne de connexion pour vous connecter correctement à votre ordinateur SQL Server, comme suit :

    cn.ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    

    Après avoir exécuté ce code, vous pouvez vous connecter à votre installation SQL Server, puis vous connecter.

  4. Enregistrez et exécutez l’application. Une fenêtre de console s’ouvre et affiche la sortie suivante :

    Update command generated by the Command Builder:
    ==================================================
    UPDATE CustTest SET CustID = @p1 , CustName = @p2 WHERE ( (CustID = @p3)
    AND ((CustName IS NULL AND @p4 IS NULL)
    OR (CustName = @p5)))
    Insert command generated by the Command Builder :
    ==================================================
    INSERT INTO CustTest( CustID , CustName ) VALUES ( @p1 , @p2 )
    Delete command generated by the Command Builder :
    ==================================================
    DELETE FROM CustTest WHERE ( (CustID = @p1)
    AND ((CustName IS NULL AND @p2 IS NULL)
    OR (CustName = @p3)))
    Customer Name before Update : John
    Customer Name after Update : Jack2
    
  5. Appuyez sur n’importe quelle touche pour fermer la fenêtre de console et arrêter l’application.

Exemple de code 2 : créer et initialiser manuellement la propriété UpdateCommand

La sortie générée par l’exemple de code 1 indique que la logique de génération automatique de commandes pour UPDATE les instructions est basée sur l’accès concurrentiel optimiste. Autrement dit, les enregistrements ne sont pas verrouillés pour modification et peuvent être modifiés par d’autres utilisateurs ou processus à tout moment. Étant donné qu’un enregistrement peut avoir été modifié après avoir été retourné à partir de l’instruction SELECT , mais avant l’émission de l’instruction UPDATE , l’instruction générée UPDATE automatiquement contient une WHERE clause de sorte qu’une ligne soit mise à jour uniquement si elle contient toutes les valeurs d’origine et n’a pas été supprimée. Cela permet de s’assurer que les nouvelles données ne sont pas remplacées. Dans les cas où une mise à jour générée automatiquement tente de mettre à jour une ligne qui a été supprimée ou ne contient pas les valeurs d’origine trouvées dans , DataSetla commande n’affecte aucun enregistrement et une DBConcurrencyException est levée.

Si vous souhaitez que le UPDATE se termine indépendamment des valeurs d’origine, vous devez définir explicitement le UpdateCommand pour plutôt DataAdapter que de vous appuyer sur la génération automatique de commandes.

Pour créer et initialiser manuellement la UpdateCommand propriété de l’objet SqlDataAdapter utilisé dans l’exemple de code 1, procédez comme suit :

  1. Copiez et collez le code suivant (en remplaçant le code existant) dans la Main() fonction dans le fichier UpdateSQL.cpp de l’application C++ créée dans l’exemple de code 1 :

    SqlConnection *cn = new SqlConnection();
    DataSet *CustomersDataSet = new DataSet();
    SqlDataAdapter *da;
    SqlCommand *DAUpdateCmd;
    cn->ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    cn->Open();
    da = new SqlDataAdapter("select * from CustTest order by CustId", cn);
    
    //Initialize the SqlCommand object that will be used as the DataAdapter's UpdateCommand
    //Notice that the WHERE clause uses only the CustId field to locate the record to be updated
    DAUpdateCmd = new SqlCommand("Update CustTest set CustName = @pCustName where CustId = @pCustId"
    , da->SelectCommand->Connection);
    
    //Create and append the parameters for the Update command
    DAUpdateCmd->Parameters->Add(new SqlParameter("@pCustName", SqlDbType::VarChar));
    DAUpdateCmd->Parameters->Item["@pCustName"]->SourceVersion = DataRowVersion::Current;
    DAUpdateCmd->Parameters->Item["@pCustName"]->SourceColumn = "CustName";
    
    DAUpdateCmd->Parameters->Add(new SqlParameter("@pCustId", SqlDbType::Int));
    DAUpdateCmd->Parameters->Item["@pCustId"]->SourceVersion = DataRowVersion::Original;
    DAUpdateCmd->Parameters->Item["@pCustId"]->SourceColumn = "CustId";
    
    //Assign the SqlCommand to the UpdateCommand property of the SqlDataAdapter
    da->UpdateCommand = DAUpdateCmd;
    da->Fill(CustomersDataSet, "Customers");
    
    DataRow *rowCust = CustomersDataSet->Tables->Item["Customers"]->Rows->Item[0];
    Console::WriteLine("Customer Name before Update : {0} ", rowCust->Item["CustName"]);
    
    //Modify the value of the CustName field
    String *newStrVal = new String("Jack");
    rowCust->set_Item("CustName", newStrVal);
    
    //Modify the value of the CustName field again
    String *newStrVal2 = new String("Jack2");
    rowCust->set_Item("CustName", newStrVal2);
    
    da->Update(CustomersDataSet, "Customers");
    Console::WriteLine("Customer Name after Update : {0} ", rowCust->Item["CustName"]);
    cn->Close();
    Console::ReadLine();
    return 0;
    
  2. Modifiez la ligne de code de chaîne de connexion dans l’exemple de code précédent comme suit :

    cn.ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    
  3. Si vous avez déjà exécuté le code dans la section exemple de code 1 de cet article, ouvrez votre table CustTestdans SQL Server, puis remplacez la valeur CustName dans le premier enregistrement par John.

  4. Enregistrez et exécutez l’application. Une fenêtre de console s’ouvre et affiche la sortie suivante :

    Customer Name before Update : John
    Customer Name after Update : Jack2