Aktualisieren einer SQL Server-Datenbank mithilfe des SqlDataAdapter-Objekts in Visual C++

In diesem Artikel wird die Verwendung des SqlDataAdapter Objekts zum Aktualisieren einer SQL Server Datenbank in Microsoft Visual C++ erläutert.

Originalversion des Produkts:   Visual C++
Ursprüngliche KB-Nummer:   308510

Zusammenfassung

Das SqlDataAdapter Objekt dient als Brücke zwischen einem ADO.NET-Objekt DataSet und einer SQL Server Datenbank. Es handelt sich um ein zwischengeschaltetes Objekt, mit dem Sie die folgenden Aktionen ausführen können:

  • Füllen Sie eine ADO.NET DataSet mit Daten auf, die aus einer SQL Server Datenbank abgerufen wurden.
  • Aktualisieren Sie die Datenbank, um die Änderungen (Einfügungen, Aktualisierungen, Löschungen) widerzuspiegeln, die mithilfe von DataSet. Dieser Artikel enthält Visual C++ .NET-Codebeispiele, um zu veranschaulichen, wie das SqlDataAdapter Objekt verwendet werden kann, um eine SQL Server Datenbank mit Datenänderungen zu aktualisieren, die für ein DataSet Objekt ausgeführt werden, das mit Daten aus einer Tabelle in der Datenbank aufgefüllt wird.

Dieser Artikel bezieht sich auf den .NET Framework KlassenbibliotheksnamespaceSystem::Data::SqlClient.

SqlDataAdapter-Objekt und -Eigenschaften

Die InsertCommand, UpdateCommandund DeleteCommand Eigenschaften des SqlDataAdapter Objekts werden verwendet, um die Datenbank mit den Datenänderungen zu aktualisieren, die für ein DataSet Objekt ausgeführt werden. Jede dieser Eigenschaften ist SqlCommand Objekte, die die entsprechenden INSERTTSQL- und DELETE TSQL-Befehle UPDATEangeben, die zum Veröffentlichen der DataSet Änderungen an der Zieldatenbank verwendet werden. Die SqlCommand diesen Eigenschaften zugewiesenen Objekte können manuell im Code erstellt oder mithilfe des SqlCommandBuilder Objekts automatisch generiert werden.

Das erste Codebeispiel in diesem Artikel veranschaulicht, wie das SqlCommandBuilder Objekt verwendet werden kann, um die UpdateCommand Eigenschaft des SqlDataAdapter Objekts automatisch zu generieren. Das zweite Beispiel verwendet ein Szenario, in dem die automatische Befehlsgenerierung nicht verwendet werden kann, und veranschaulicht daher den Prozess, mit dem Sie ein SqlCommand Objekt manuell erstellen und als UpdateCommand Eigenschaft eines SqlDataAdapter Objekts verwenden können.

Erstellen des Beispiels SQL Server Tabelle

Führen Sie die folgenden Schritte aus, um ein Beispiel SQL Server Tabelle zu erstellen, die in den in diesem Artikel dokumentierten Visual C++-.NET-Codebeispielen verwendet werden kann:

  1. Öffnen Sie SQL Server Query Analyzer, und stellen Sie dann eine Verbindung mit einer Datenbank her, in der Sie die Beispieltabelle erstellen möchten. In den Codebeispielen in diesem Artikel wird die Northwind-Datenbank verwendet, die im Lieferumfang von SQL Server enthalten ist.

  2. Führen Sie die folgenden T-SQL-Anweisungen aus, um eine Beispieltabelle namens CustTest zu erstellen, und fügen Sie dann einen Datensatz in die Tabelle ein.

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

Codebeispiel 1: Automatisch generierte Befehle

Wenn die SELECT Anweisung zum Abrufen der Daten, die zum Auffüllen einer DataSet Datenbank verwendet werden, auf einer einzigen Datenbanktabelle basiert, können Sie das CommandBuilder Objekt nutzen, um automatisch die DeleteCommand, InsertCommandund UpdateCommand Eigenschaften der DataAdapterzu generieren. Dies vereinfacht und reduziert den Code, der zum Ausführen INSERTvon DELETE Vorgängen UDPATEerforderlich ist.

Als Mindestanforderung müssen Sie die Eigenschaft festlegen, damit die SelectCommand automatische Befehlsgenerierung funktioniert. Das tabellenschema abgerufen von der SelectCommand bestimmt die Syntax der automatisch generierten INSERT, UPDATEund DELETE Anweisungen.

Außerdem SelectCommand muss mindestens ein Primärschlüssel oder eine eindeutige Spalte zurückgegeben werden. Wenn keine vorhanden ist, wird eine InvalidOperation Ausnahme generiert, und die Befehle werden nicht generiert.

Führen Sie die folgenden Schritte aus, um eine Visual C++ .NET-Beispielkonsolenanwendung zu erstellen, die veranschaulicht, wie das SqlCommandBuilder Objekt zum automatischen Generieren der InsertCommandObjekteigenschaften ", DeleteCommand" und UpdateCommand "SqlCommand" für ein SqlDataAdapter Objekt verwendet wird:

  1. Starten Sie Visual Studio .NET, und erstellen Sie dann eine neue verwaltete C++-Anwendung. Nennen Sie es "updateSQL".

  2. Kopieren Sie den folgenden Code, und fügen Sie ihn in "updateSQL.cpp " ein (wobei der Standardinhalt ersetzt wird):

    #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. Ändern Sie in dem Code, den Sie in Schritt 2 kopiert und eingefügt haben, die Zeile des Verbindungszeichenfolgencodes, um eine ordnungsgemäße Verbindung mit Ihrem SQL Server Computer herzustellen, wie folgt:

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

    Nachdem Sie diesen Code ausgeführt haben, können Sie eine Verbindung mit Ihrer SQL Server Installation herstellen und sich dann anmelden.

  4. Speichern und ausführen Sie die Anwendung. Ein Konsolenfenster wird geöffnet und zeigt die folgende Ausgabe an:

    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. Drücken Sie eine beliebige Taste, um das Konsolenfenster zu schließen und die Anwendung zu beenden.

Codebeispiel 2: Manuelles Erstellen und Initialisieren der UpdateCommand-Eigenschaft

Die im Codebeispiel 1 generierte Ausgabe gibt an, dass die Logik zum automatischen Generieren von Befehlen für UPDATE Anweisungen auf optimistischer Parallelität basiert. Das heißt, Datensätze sind nicht für die Bearbeitung gesperrt und können jederzeit von anderen Benutzern oder Prozessen geändert werden. Da ein Datensatz möglicherweise geändert wurde, nachdem er von der SELECT Anweisung zurückgegeben wurde, aber bevor die UPDATE Anweisung ausgegeben wird, enthält die automatisch generierte UPDATE Anweisung eine WHERE Klausel, sodass eine Zeile nur aktualisiert wird, wenn sie alle ursprünglichen Werte enthält und nicht gelöscht wurde. Dadurch wird sichergestellt, dass neue Daten nicht überschrieben werden. In Fällen, in denen eine automatisch generierte Aktualisierung versucht, eine Zeile zu aktualisieren, die gelöscht wurde oder nicht die ursprünglichen Werte enthält, die in der DataSetDatei gefunden wurden, wirkt sich der Befehl nicht auf Datensätze aus, und ein DBConcurrencyException Befehl wird ausgelöst.

Wenn sie unabhängig von den UPDATE ursprünglichen Werten abgeschlossen werden soll, müssen Sie die Option explizit für die UpdateCommand DataAdapter Generierung von Befehlen festlegen, anstatt sich auf die automatische Befehlsgenerierung zu verlassen.

Führen Sie die folgenden Schritte aus, um die UpdateCommand Eigenschaft des SqlDataAdapter im Codebeispiel 1 verwendeten Objekts manuell zu erstellen und zu initialisieren:

  1. Kopieren Sie den folgenden Code (überschreiben Sie den vorhandenen Code), und fügen Sie ihn in die Main() Funktion in der Datei "UpdateSQL.cpp " in der C++-Anwendung ein, die im Codebeispiel 1 erstellt wurde:

    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. Ändern Sie die Zeile des Verbindungszeichenfolgencodes im vorherigen Codebeispiel wie folgt:

    cn.ConnectionString = "Server=server;Database=northwind;UID=login;PWD=password;";
    
  3. Wenn Sie den Code bereits im Codebeispiel 1 dieses Artikels ausgeführt haben, öffnen Sie Ihre CustTesttable in SQL Server, und ändern Sie dann den CustName-Wert im ersten Datensatz wieder in John.

  4. Speichern und ausführen Sie die Anwendung. Ein Konsolenfenster wird geöffnet und zeigt die folgende Ausgabe an:

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