Generieren von Befehlen mit CommandBuilder-ObjektenGenerating Commands with CommandBuilders

Wenn die SelectCommand-Eigenschaft dynamisch zur Laufzeit angegeben wird, z. B. mit einem Abfragetool, in dem der Benutzer einen Textbefehl eingibt, sind Sie zur Entwurfszeit u. U. nicht in der Lage, den entsprechenden InsertCommand, UpdateCommand oder DeleteCommand anzugeben.When the SelectCommand property is dynamically specified at run time, such as through a query tool that takes a textual command from the user, you may not be able to specify the appropriate InsertCommand, UpdateCommand, or DeleteCommand at design time. Wenn Ihre DataTable einer einzelnen Datenbanktabelle zugeordnet ist oder aus einer solchen generiert wurde, können Sie mithilfe des DbCommandBuilder-Objekts automatisch den DeleteCommand, den InsertCommand und den UpdateCommand des DbDataAdapter generieren.If your DataTable maps to or is generated from a single database table, you can take advantage of the DbCommandBuilder object to automatically generate the DeleteCommand, InsertCommand, and UpdateCommand of the DbDataAdapter.

Damit die automatische Befehlsgenerierung funktioniert, muss mindestens die SelectCommand-Eigenschaft festgelegt werden.As a minimum requirement, you must set the SelectCommand property in order for automatic command generation to work. Das durch die SelectCommand-Eigenschaft abgerufene Tabellenschema bestimmt die Syntax der automatisch generierten INSERT-, UPDATE- und DELETE-Anweisungen.The table schema retrieved by the SelectCommand property determines the syntax of the automatically generated INSERT, UPDATE, and DELETE statements.

Der DbCommandBuilder muss SelectCommand ausführen, damit die zum Konstruieren der SQL-Befehle INSERT, UPDATE und DELETE erforderlichen Metadaten zurückgegeben werden.The DbCommandBuilder must execute the SelectCommand in order to return the metadata necessary to construct the INSERT, UPDATE, and DELETE SQL commands. Daher ist ein erneutes Lesen der Datenquelle erforderlich, was die Leistung herabsetzen kann.As a result, an extra trip to the data source is necessary, and this can hinder performance. Eine optimale Leistung lässt sich erzielen, indem Sie die Befehle direkt angeben, anstatt den DbCommandBuilder zu verwenden.To achieve optimal performance, specify your commands explicitly rather than using the DbCommandBuilder.

Der SelectCommand muss außerdem mindestens einen Primärschlüssel oder eine eindeutige Spalte zurückgeben.The SelectCommand must also return at least one primary key or unique column. Wenn weder das eine noch das andere vorhanden ist, wird eine InvalidOperation-Ausnahme ausgelöst, und die Befehle werden nicht generiert.If none are present, an InvalidOperation exception is generated, and the commands are not generated.

Bei einer Zuordnung zu einem DataAdapter generiert der DbCommandBuilder automatisch die Eigenschaften InsertCommand, UpdateCommand und DeleteCommand des DataAdapter, sofern es sich um NULL-Verweise handelt.When associated with a DataAdapter, the DbCommandBuilder automatically generates the InsertCommand, UpdateCommand, and DeleteCommand properties of the DataAdapter if they are null references. Wenn für eine Eigenschaft bereits ein Command vorhanden ist, wird der vorhandene Command verwendet.If a Command already exists for a property, the existing Command is used.

Datenbankansichten, die durch das Verknüpfen von zwei oder mehr Datenbanken erstellt wurden, werden nicht als eine einzelne Datenbanktabelle betrachtet.Database views that are created by joining two or more tables together are not considered a single database table. In dieser Instanz können Sie den DbCommandBuilder nicht zum automatischen Generieren von Befehlen verwenden; Sie müssen die Befehle explizit angeben.In this instance you cannot use the DbCommandBuilder to automatically generate commands; you must specify your commands explicitly. Informationen zum expliziten Festlegen von Befehlen zum Aktualisieren einer DataSet zurück an die Datenquelle finden Sie unter Aktualisieren von Datenquellen mit "DataAdapters".For information about explicitly setting commands to resolve updates to a DataSet back to the data source, see Updating Data Sources with DataAdapters.

Unter Umständen möchten Sie der aktualisierten Zeile eines DataSet erneut Ausgabeparameter zuordnen.You might want to map output parameters back to the updated row of a DataSet. Eine allgemeine Aufgabe wäre das Abrufen des Werts eines automatisch generierten Identitätsfelds oder Timestamps aus der Datenquelle.One common task would be retrieving the value of an automatically generated identity field or time stamp from the data source. Standardmäßig werden den Spalten in einer aktualisierten Zeile vom DbCommandBuilder keine Ausgabeparameter zugeordnet.The DbCommandBuilder will not map output parameters to columns in an updated row by default. In diesem Fall müssen Sie den Befehl explizit angeben.In this instance you must specify your command explicitly. Ein Beispiel für die Zuordnung eines automatisch generierten Identitätsfelds zu einer Spalte einer eingefügten Zeile, finden Sie unter Abrufen von Identity- oder Autonumber-Werten.For an example of mapping an automatically generated identity field back to a column of an inserted row, see Retrieving Identity or Autonumber Values.

Regeln für automatisch generierte BefehleRules for Automatically Generated Commands

Die folgende Tabelle enthält die Regeln für das Generieren von automatisch generierten Befehlen.The following table shows the rules for how automatically generated commands are generated.

BefehlCommand RegelRule
InsertCommand Fügt in der Datenquelle für alle Zeilen in der Tabelle, die den RowStateAdded aufweisen, eine Zeile ein.Inserts a row at the data source for all rows in the table with a RowState of Added. Fügt Werte für alle Spalten ein, die aktualisiert werden können (jedoch nicht für Spalten wie Identitäten, Ausdrücke oder Timestamps).Inserts values for all columns that are updateable (but not columns such as identities, expressions, or timestamps).
UpdateCommand Aktualisiert Zeilen in der Datenquelle für alle Zeilen in der Tabelle, die den RowState-Wert Modified aufweisen.Updates rows at the data source for all rows in the table with a RowState of Modified. Aktualisiert die Werte aller Spalten mit Ausnahme von Spalten, die nicht aktualisiert werden können, z. B. Identitäten oder Ausdrücke.Updates the values of all columns except for columns that are not updateable, such as identities or expressions. Aktualisiert alle Zeilen, deren Spaltenwerte in der Datenquelle den Primärschlüssel-Spaltenwerten der Zeile entsprechen und bei denen die übrigen Spalten in der Datenquelle den ursprünglichen Werten der Zeile entsprechen.Updates all rows where the column values at the data source match the primary key column values of the row, and where the remaining columns at the data source match the original values of the row. Weitere Informationen finden Sie unter "Vollständiges Parallelitätsmodell für Updates und Löschvorgänge" weiter unten in diesem Thema.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.
DeleteCommand Löscht Zeilen in der Datenquelle für alle Zeilen in der Tabelle, die den RowState-Wert Deleted aufweisen.Deletes rows at the data source for all rows in the table with a RowState of Deleted. Löscht alle Zeilen, deren Spaltenwerte den Primärschlüssel-Spaltenwerten der Zeile entsprechen und bei denen die übrigen Spalten in der Datenquelle den ursprünglichen Werten der Zeile entsprechen.Deletes all rows where the column values match the primary key column values of the row, and where the remaining columns at the data source match the original values of the row. Weitere Informationen finden Sie unter "Vollständiges Parallelitätsmodell für Updates und Löschvorgänge" weiter unten in diesem Thema.For more information, see "Optimistic Concurrency Model for Updates and Deletes," later in this topic.

Vollständiges Parallelitätsmodell für Updates und LöschvorgängeOptimistic Concurrency Model for Updates and Deletes

Die Logik für das Generieren von Befehlen für Update- und DELETE-Anweisungen automatisch basiert auf optimistische Parallelität–, also die Datensätze werden nicht für die Bearbeitung gesperrt und kann von anderen Benutzern oder Prozessen jederzeit geändert werden.The logic for generating commands automatically for UPDATE and DELETE statements is based on optimistic concurrency--that is, records are not locked for editing and can be modified by other users or processes at any time. Da ein Datensatz nach der Rückgabe aus der SELECT-Anweisung und vor der Ausführung der UPDATE- oder DELETE-Anweisung ggf. geändert wurde, enthält die automatisch generierte UPDATE- oder DELETE-Anweisung eine WHERE-Klausel, die angibt, dass eine Zeile nur dann aktualisiert wird, wenn sie alle ursprünglichen Werte enthält und nicht aus der Datenquelle gelöscht wurde.Because a record could have been modified after it was returned from the SELECT statement, but before the UPDATE or DELETE statement is issued, the automatically generated UPDATE or DELETE statement contains a WHERE clause, specifying that a row is only updated if it contains all original values and has not been deleted from the data source. Hierdurch wird vermieden, dass neue Daten überschrieben werden.This is done to avoid overwriting new data. In Fällen, in denen ein automatisch generierter Updatebefehl versucht, eine Zeile zu aktualisieren, die gelöscht wurde oder nicht die ursprünglichen Werte im DataSet enthält, hat der Befehl keine Auswirkungen auf Datensätze, und es wird eine DBConcurrencyException ausgelöst.Where an automatically generated update attempts to update a row that has been deleted or that does not contain the original values found in the DataSet, the command does not affect any records, and a DBConcurrencyException is thrown.

Wenn UPDATE oder DELETE unabhängig von den ursprünglichen Werten ausgeführt werden sollen, muss der UpdateCommand für den DataAdapter explizit festgelegt und die automatische Befehlsgenerierung damit außer Kraft gesetzt werden.If you want the UPDATE or DELETE to complete regardless of original values, you must explicitly set the UpdateCommand for the DataAdapter and not rely on automatic command generation.

Einschränkungen der Logik für die automatische Generierung von BefehlenLimitations of Automatic Command Generation Logic

Folgende Einschränkungen gelten für die automatische Generierung von Befehlen.The following limitations apply to automatic command generation.

Nur nicht verknüpfte TabellenUnrelated Tables Only

Die Logik für die automatische Generierung von Befehlen generiert INSERT-, UPDATE- oder DELETE-Befehle für eigenständige Tabellen, wobei Verknüpfungen mit anderen Tabellen in der Datenquelle unberücksichtigt bleiben.The automatic command generation logic generates INSERT, UPDATE, or DELETE statements for stand-alone tables without taking into account any relationships to other tables at the data source. Daher kann ein Fehler auftreten, wenn Sie Update aufrufen, um Änderungen an einer Spalte zu übermitteln, die in der Datenbank Fremdschlüsseleinschränkungen unterworfen ist.As a result, you may encounter a failure when calling Update to submit changes for a column that participates in a foreign key constraint in the database. Sie können diese Ausnahme vermeiden, indem Sie zum Aktualisieren von Spalten, die einer Einschränkung eines Fremdschlüssels unterworfen sind, nicht den DbCommandBuilder verwenden, sondern die Anweisungen zur Durchführung der Operation explizit angeben.To avoid this exception, do not use the DbCommandBuilder for updating columns involved in a foreign key constraint; instead, explicitly specify the statements used to perform the operation.

Tabellennamen und SpaltennamenTable and Column Names

Die Logik für die automatische Befehlsgenerierung kann fehlschlagen, wenn Spalten- oder Tabellennamen Sonderzeichen wie Leerzeichen, Punkte, Anführungszeichen oder andere nicht alphanumerische Zeichen enthalten, selbst wenn diese durch Klammern getrennt sind.Automatic command generation logic may fail if column names or table names contain any special characters, such as spaces, periods, quotation marks, or other nonalphanumeric characters, even if delimited by brackets. Leerzeichen können je nach Anbieter von der Generierungslogik durch Festlegen des QuotePrefix-Parameters und QuoteSuffix-Parameters möglicherweise verarbeitet werden, Sonderzeichen können jedoch nicht mit Escapezeichen versehen werden.Depending on the provider, setting the QuotePrefix and QuoteSuffix parameters may allow the generation logic to process spaces, but it cannot escape special characters. Vollqualifizierte Tabellennamen in Form von catalog.schema.table werden unterstützt.Fully qualified table names in the form of catalog.schema.table are supported.

Verwenden des CommandBuilder-Objekts zum automatischen Generieren einer SQL-AnweisungUsing the CommandBuilder to Automatically Generate an SQL Statement

Legen Sie zum automatischen Generieren von SQL-Anweisungen für einen DataAdapter zuerst die SelectCommand-Eigenschaft des DataAdapter fest. Erstellen Sie dann ein CommandBuilder-Objekt, und geben Sie als Argument den DataAdapter an, für den der CommandBuilder automatisch SQL-Anweisungen generieren soll.To automatically generate SQL statements for a DataAdapter, first set the SelectCommand property of the DataAdapter, then create a CommandBuilder object, and specify as an argument the DataAdapter for which the CommandBuilder will automatically generate SQL statements.

' Assumes that connection is a valid SqlConnection object   
' inside of a Using block.  
Dim adapter As SqlDataAdapter = New SqlDataAdapter( _  
  "SELECT * FROM dbo.Customers", connection)  
Dim builder As SqlCommandBuilder = New SqlCommandBuilder(adapter)  
builder.QuotePrefix = "["  
builder.QuoteSuffix = "]"  
// Assumes that connection is a valid SqlConnection object  
// inside of a using block.  
SqlDataAdapter adapter = new SqlDataAdapter(  
  "SELECT * FROM dbo.Customers", connection);  
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);  
builder.QuotePrefix = "[";  
builder.QuoteSuffix = "]";  

Ändern von SelectCommandModifying the SelectCommand

Wenn Sie den CommandText von SelectCommand ändern, nachdem die Befehle INSERT, UPDATE oder DELETE automatisch generiert wurden, kann eine Ausnahme auftreten.If you modify the CommandText of the SelectCommand after the INSERT, UPDATE, or DELETE commands have been automatically generated, an exception may occur. Wenn der geänderte SelectCommand.CommandText Schemainformationen enthält, die nicht mit dem SelectCommand.CommandText zum Zeitpunkt der automatischen Generierung der Befehle INSERT, UPDATE oder DELETE konsistent sind, wird bei späteren Aufrufen der DataAdapter.Update-Methode möglicherweise versucht, auf Spalten zuzugreifen, die nicht mehr in der aktuellen Tabelle vorhanden sind, auf die SelectCommand verweist. In diesem Fall wird eine Ausnahme ausgelöst.If the modified SelectCommand.CommandText contains schema information that is inconsistent with the SelectCommand.CommandText used when the insert, update, or delete commands were automatically generated, future calls to the DataAdapter.Update method may attempt to access columns that no longer exist in the current table referenced by the SelectCommand, and an exception will be thrown.

Sie können die vom CommandBuilder zum automatischen Generieren von Befehlen verwendeten Schemainformationen aktualisieren, indem Sie die RefreshSchema-Methode des CommandBuilder aufrufen.You can refresh the schema information used by the CommandBuilder to automatically generate commands by calling the RefreshSchema method of the CommandBuilder.

Wenn Sie wissen möchten, welcher Befehl automatisch generiert wurde, können Sie mit den Methoden GetInsertCommand, GetUpdateCommand und GetDeleteCommand des CommandBuilder-Objekts Verweise auf die Befehle abrufen und die CommandText-Eigenschaft des zugeordneten Befehls überprüfen.If you want to know what command was automatically generated, you can obtain a reference to the automatically generated commands by using the GetInsertCommand, GetUpdateCommand, and GetDeleteCommand methods of the CommandBuilder object and checking the CommandText property of the associated command.

Im folgenden Codebeispiel wird der automatisch generierte UPDATE-Befehl in die Konsole geschrieben.The following code example writes to the console the update command that was automatically generated.

Console.WriteLine(builder.GetUpdateCommand().CommandText)  
Console.WriteLine(builder.GetUpdateCommand().CommandText);

Das folgende Beispiel erstellt die Customers-Tabelle im custDS-Dataset neu.The following example recreates the Customers table in the custDS dataset. Die RefreshSchema Methode wird aufgerufen, um die automatisch generierten Befehle mit den neuen Spalteninformationen zu aktualisieren.The RefreshSchema method is called to refresh the automatically generated commands with this new column information.

' Assumes an open SqlConnection and SqlDataAdapter inside of a Using block.  
adapter.SelectCommand.CommandText = _  
  "SELECT CustomerID, ContactName FROM dbo.Customers"  
builder.RefreshSchema()  
  
custDS.Tables.Remove(custDS.Tables("Customers"))  
adapter.Fill(custDS, "Customers")  
// Assumes an open SqlConnection and SqlDataAdapter inside of a using block.  
adapter.SelectCommand.CommandText =   
  "SELECT CustomerID, ContactName FROM dbo.Customers";  
builder.RefreshSchema();  
  
custDS.Tables.Remove(custDS.Tables["Customers"]);  
adapter.Fill(custDS, "Customers");  

Siehe auchSee also