Aggiornare un database SQL Server usando l'oggetto SqlDataAdapter in Visual C++

Questo articolo illustra come usare l'oggetto SqlDataAdapter per aggiornare un database SQL Server in Microsoft Visual C++.

Versione originale del prodotto: Visual C++
Numero KB originale: 308510

Riepilogo

L'oggetto SqlDataAdapter funge da ponte tra un oggetto ADO.NET DataSet e un database SQL Server. Si tratta di un oggetto intermedio che è possibile usare per eseguire le operazioni seguenti:

  • Popolare un ADO.NET DataSet con i dati recuperati da un database SQL Server.
  • Aggiornare il database in modo che rifletta le modifiche (inserimenti, aggiornamenti, eliminazioni) apportate ai dati tramite DataSet. Questo articolo fornisce esempi di codice .NET di Visual C++ per illustrare come usare l'oggetto SqlDataAdapter per aggiornare un database SQL Server con modifiche ai dati eseguite su un DataSet oggetto popolato con dati da una tabella nel database.

Questo articolo fa riferimento allo spazio dei nomi System::Data::SqlClientdella libreria di classi .NET Framework.

Proprietà e oggetto SqlDataAdapter

Le InsertCommandproprietà , UpdateCommande DeleteCommand dell'oggetto SqlDataAdapter vengono utilizzate per aggiornare il database con le modifiche ai dati eseguite su un DataSet oggetto . Ognuna di queste proprietà è SqlCommand costituita da oggetti che specificano i rispettivi INSERTcomandi , UPDATEe DELETE TSQL usati per pubblicare le DataSet modifiche al database di destinazione. Gli SqlCommand oggetti assegnati a queste proprietà possono essere creati manualmente nel codice o generati automaticamente tramite l'oggetto SqlCommandBuilder .

Il primo esempio di codice in questo articolo illustra come usare l'oggetto SqlCommandBuilder per generare automaticamente la UpdateCommand proprietà dell'oggetto SqlDataAdapter . Il secondo esempio usa uno scenario in cui non è possibile usare la UpdateCommand generazione automatica di comandi e quindi illustra il processo tramite il quale è possibile creare e usare manualmente un SqlCommand oggetto come proprietà di un SqlDataAdapter oggetto.

Creare la tabella di SQL Server di esempio

Per creare una tabella SQL Server di esempio da usare negli esempi di codice .NET di Visual C++ documentati in questo articolo, seguire questa procedura:

  1. Aprire SQL Server Analizzatore query e quindi connettersi a un database in cui si vuole creare la tabella di esempio. Gli esempi di codice in questo articolo usano il database Northwind fornito con SQL Server.

  2. Eseguire le istruzioni T-SQL seguenti per creare una tabella di esempio denominata CustTest e quindi inserirvi un record.

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

Esempio di codice 1: Comandi generati automaticamente

Se l'istruzione SELECT per recuperare i dati utilizzati per popolare un DataSet oggetto è basata su una singola tabella di database, è possibile sfruttare l'oggetto CommandBuilder per generare automaticamente le DeleteCommandproprietà , InsertCommande UpdateCommand di DataAdapter. Ciò semplifica e riduce il codice necessario per eseguire INSERToperazioni , UPDATEe DELETE .

Come requisito minimo, è necessario impostare la proprietà per il funzionamento della SelectCommand generazione automatica dei comandi. Lo schema di tabella recuperato da SelectCommand determina la sintassi delle istruzioni , UPDATEe DELETE generate INSERTautomaticamente.

Deve SelectCommand inoltre restituire almeno una chiave primaria o una colonna univoca. Se non è presente, viene generata un'eccezione InvalidOperation e i comandi non vengono generati.

Per creare un'applicazione console di Visual C++ .NET di esempio che illustra come usare l'oggetto SqlCommandBuilder per generare automaticamente le proprietà dell'oggetto InsertCommand, DeleteCommande UpdateCommand SqlCommand per un SqlDataAdapter oggetto, seguire questa procedura:

  1. Avviare Visual Studio .NET e quindi creare una nuova applicazione C++ gestita. Assegnare il nome updateSQL.

  2. Copiare e incollare il codice seguente in updateSQL.cpp (sostituendone il contenuto predefinito):

    #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. Nel codice copiato e incollato nel passaggio 2 modificare la riga di codice stringa di connessione per connettersi correttamente al computer SQL Server, come indicato di seguito:

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

    Dopo aver eseguito questo codice, è possibile connettersi all'installazione di SQL Server e quindi accedere.

  4. Salvare ed eseguire l'applicazione. Verrà aperta una finestra della console e verrà visualizzato l'output seguente:

    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. Premere un tasto qualsiasi per chiudere la finestra della console e arrestare l'applicazione.

Esempio di codice 2: Creare e inizializzare manualmente la proprietà UpdateCommand

L'output generato dall'esempio di codice 1 indica che la logica per la generazione automatica dei comandi per UPDATE le istruzioni è basata sulla concorrenza ottimistica. Ovvero, i record non sono bloccati per la modifica e possono essere modificati da altri utenti o processi in qualsiasi momento. Poiché un record può essere stato modificato dopo che è stato restituito dall'istruzione SELECT ma prima dell'istruzione , l'istruzione UPDATE generata UPDATE automaticamente contiene una WHERE clausola in modo che una riga venga aggiornata solo se contiene tutti i valori originali e non è stata eliminata. Questa operazione viene eseguita per garantire che i nuovi dati non vengano sovrascritti. Nei casi in cui un aggiornamento generato automaticamente tenta di aggiornare una riga che è stata eliminata o non contiene i valori originali trovati in DataSet, il comando non influisce su alcun record e viene generato un DBConcurrencyException oggetto .

Se si vuole che l'oggetto UPDATE venga completato indipendentemente dai valori originali, è necessario impostare UpdateCommand in modo esplicito per DataAdapter anziché basarsi sulla generazione automatica dei comandi.

Per creare e inizializzare manualmente la UpdateCommand proprietà dell'oggetto SqlDataAdapter usato nell'esempio di codice 1, seguire questa procedura:

  1. Copiare e incollare il codice seguente (sovrascrivendo il codice esistente) nella Main() funzione all'interno del file UpdateSQL.cpp nell'applicazione C++ creata nell'esempio di codice 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. Modificare la riga di codice stringa di connessione nell'esempio di codice precedente nel modo seguente:

    cn.ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    
  3. Se il codice è già stato eseguito nella sezione 1 dell'esempio di codice di questo articolo, aprire la tabella CustTestin SQL Server e quindi modificare di nuovo il valore CustName nel primo record in John.

  4. Salvare ed eseguire l'applicazione. Verrà aperta una finestra della console e verrà visualizzato l'output seguente:

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