Freigeben über


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

In diesem Artikel wird erläutert, wie Sie das SqlDataAdapter Objekt zum Aktualisieren einer SQL Server-Datenbank in Microsoft Visual C++ verwenden.

Originalproduktversion: 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 folgendes ausführen können:

  • Füllen Sie eine ADO.NET DataSet mit Daten, die aus einer SQL Server-Datenbank abgerufen wurden.
  • Aktualisieren Sie die Datenbank so, dass sie die Änderungen (Einfügungen, Aktualisierungen, Löschungen) an den Daten mithilfe der 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 auf einem 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-Klassenbibliotheksnamespace System::Data::SqlClient.

SqlDataAdapter-Objekt und -Eigenschaften

Die InsertCommandEigenschaften 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 INSERTBefehle UPDATEund DELETE TSQL-Befehle angeben, mit denen die DataSet Änderungen an der Zieldatenbank gepostet 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. Im zweiten Beispiel wird ein Szenario verwendet, in dem die automatische Befehlsgenerierung nicht verwendet werden kann, und zeigt daher den Prozess, mit dem Sie ein SqlCommand Objekt manuell als UpdateCommand Eigenschaft eines SqlDataAdapter Objekts erstellen und verwenden können.

Erstellen der SQL Server-Beispieltabelle

Führen Sie die folgenden Schritte aus, um eine SQL Server-Beispieltabelle zu erstellen, die in den in diesem Artikel dokumentierten .NET-Codebeispielen von Visual C++ verwendet werden soll:

  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 ihn 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 Daten verwendet werden, auf einer einzelnen Datenbanktabelle basiert, können Sie das CommandBuilder Objekt nutzen, um die DeleteCommandEigenschaften InsertCommandund UpdateCommand Eigenschaften des DataAdapterObjekts automatisch zu generieren. Dadurch wird der code vereinfacht und reduziert, der zum Ausführen INSERT, Ausführen von Vorgängen UPDATEund DELETE Vorgängen erforderlich ist.

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

Der SelectCommand muss außerdem mindestens einen Primärschlüssel oder eine eindeutige Spalte zurückgeben. Falls kein Schlüssel bzw. keine Spalte vorhanden ist, wird anstelle der Befehle eine InvalidOperation-Ausnahme generiert.

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

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

  2. Kopieren Sie den folgenden Code, und fügen Sie ihn in updateSQL.cpp ein (ersetzen Sie den Standardinhalt):

    #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 im code, den Sie in Schritt 2 kopiert und eingefügt haben, die Zeile des Verbindungszeichenfolgencodes so, dass eine ordnungsgemäße Verbindung mit Ihrem SQL Server-Computer hergestellt wird:

    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 vom 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. Dies geschieht, um sicherzustellen, dass neue Daten nicht überschrieben werden. In Fällen, in denen ein automatisch generiertes Update versucht, eine Zeile zu aktualisieren, die gelöscht wurde oder nicht die ursprünglichen Werte enthält, die DataSetim Dokument gefunden wurden, hat der Befehl keine Auswirkungen auf Datensätze und wird DBConcurrencyException ausgelöst.

Wenn sie UPDATE unabhängig von den ursprünglichen Werten abgeschlossen werden sollen, müssen Sie den UpdateCommand Wert für die DataAdapter automatische Befehlsgenerierung explizit festlegen.

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) in die Main() Funktion in der datei UpdateSQL.cpp in der im Codebeispiel 1 erstellten C++-Anwendung, und fügen Sie ihn ein:

    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 Abschnitt dieses Artikels ausgeführt haben, öffnen Sie Ihre CustTest-Tabellein 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