Freigeben über


Generieren von Befehlen mit CommandBuilder-Objekten

Gilt für: .NET Framework .NET .NET Standard

Herunterladen von ADO.NET

Wenn die SelectCommand-Eigenschaft des DbDataAdapter-Objekts zur Laufzeit dynamisch angegeben wird (z. B. über ein Abfragetool, das einen Textbefehl des Benutzers ausführt), können Sie die jeweiligen InsertCommand-, UpdateCommand- oder DeleteCommand-Befehle möglicherweise nicht zur Entwurfszeit angeben. 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.

Hinweis

Im Microsoft SqlClient-Datenanbieter für SQL Server wird die Klasse SqlDataAdapter von der Klasse DbDataAdapter und die Klasse SqlCommandBuilder von der Klasse DbCommandBuilder abgeleitet.

Damit die automatische Befehlsgenerierung funktioniert, muss mindestens die SelectCommand-Eigenschaft festgelegt werden. Das durch die SelectCommand-Eigenschaft abgerufene Tabellenschema bestimmt die Syntax der automatisch generierten INSERT-, UPDATE- und DELETE-Anweisungen.

Der DbCommandBuilder muss SelectCommand ausführen, damit die zum Konstruieren der SQL-Befehle INSERT, UPDATE und DELETE erforderlichen Metadaten zurückgegeben werden. Daher ist ein erneutes Lesen der Datenquelle erforderlich, was die Leistung herabsetzen kann. Eine optimale Leistung lässt sich erzielen, indem Sie die Befehle direkt angeben, anstatt den DbCommandBuilder zu verwenden.

Hinweis

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.

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. Wenn für eine Eigenschaft bereits ein Command vorhanden ist, wird der vorhandene Command verwendet.

Datenbankansichten, die durch das Verknüpfen von zwei oder mehr Datenbanken erstellt wurden, werden nicht als eine einzelne Datenbanktabelle betrachtet. Bei dieser Instanz kann DbCommandBuilder nicht verwendet werden, um Befehle automatisch zu generieren. Die Befehle müssen explizit angegeben werden. Informationen, wie Sie explizit Befehle zum Aktualisieren der Datenquelle mit DataSet-Änderungen festlegen können, finden Sie unter Aktualisieren von Datenquellen mit DataAdapters.

Unter Umständen möchten Sie der aktualisierten Zeile eines DataSet erneut Ausgabeparameter zuordnen. Eine allgemeine Aufgabe wäre das Abrufen des Werts eines automatisch generierten Identitätsfelds oder Timestamps aus der Datenquelle. Standardmäßig werden den Spalten in einer aktualisierten Zeile vom DbCommandBuilder keine Ausgabeparameter zugeordnet. Bei dieser Instanz muss der Befehl explizit angegeben werden. Ein Beispiel für das erneute Zuordnen eines automatisch generierten Identitätsfelds zu einer Spalte einer eingefügten Zeile finden Sie unter Abrufen von Identity- oder Autonumber-Werten.

Regeln für automatisch generierte Befehle

Die folgende Tabelle enthält die Regeln für das Generieren von automatisch generierten Befehlen.

Get-Help Regel
InsertCommand Fügt in der Datenquelle für alle Zeilen in der Tabelle, die den RowStateAdded aufweisen, eine Zeile ein. 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).
UpdateCommand Aktualisiert Zeilen in der Datenquelle für alle Zeilen in der Tabelle, die den RowState-Wert Modified aufweisen. Aktualisiert die Werte aller Spalten mit Ausnahme von Spalten, die nicht aktualisiert werden können, z. B. Identitäten oder Ausdrücke. 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. Weitere Informationen finden Sie unter "Vollständiges Parallelitätsmodell für Updates und Löschvorgänge" weiter unten in diesem Thema.
DeleteCommand Löscht Zeilen in der Datenquelle für alle Zeilen in der Tabelle, die den RowState-Wert Deleted aufweisen. 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. Weitere Informationen finden Sie unter Optimistisches Parallelitätsmodell für Updates und Löschvorgänge weiter unten in diesem Thema.

Optimistisches Parallelitätsmodell für Updates und Löschvorgänge

Die Logik beim automatischen Generieren von Befehlen für UPDATE- und DELETE-Anweisungen basiert auf der optimistischen Parallelität, d. h., die Datensätze werden für die Bearbeitung nicht gesperrt und können von anderen Benutzern oder Prozessen jederzeit geändert werden. 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. Hierdurch wird vermieden, dass neue Daten überschrieben werden.

Hinweis

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.

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.

Einschränkungen der Logik für das automatische Generieren von Befehlen

Folgende Einschränkungen gelten für die automatische Generierung von Befehlen.

Nur nicht verknüpfte Tabellen

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. 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. 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.

Tabellen- und Spaltennamen

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. 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. Vollqualifizierte Tabellennamen der Form catalog.schema.table werden unterstützt.

Verwenden von CommandBuilder zum automatischen Generieren einer SQL-Anweisung

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.

// Assumes that connection is a valid SqlConnection object  
// inside of a using block. 
SqlDataAdapter adapter = new SqlDataAdapter();
adapter.SelectCommand = new SqlCommand(queryString, connection);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
builder.QuotePrefix = "[";  
builder.QuoteSuffix = "]";  

Ändern von SelectCommand

Wenn Sie den CommandText von SelectCommand ändern, nachdem die Befehle INSERT, UPDATE oder DELETE automatisch generiert wurden, kann eine Ausnahme auftreten. 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.

Sie können die vom CommandBuilder zum automatischen Generieren von Befehlen verwendeten Schemainformationen aktualisieren, indem Sie die RefreshSchema-Methode des CommandBuilder aufrufen.

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.

Im folgenden Codebeispiel wird der automatisch generierte UPDATE-Befehl in die Konsole geschrieben.

// Generate the update command automatically by SqlCommandBuilder
Console.WriteLine(builder.GetUpdateCommand().CommandText);

Das folgende Beispiel erstellt die -Tabelle im -Dataset neu. Die RefreshSchema-Methode wird zum Aktualisieren der automatisch generierten Befehle mit den neuen Spalteninformationen aufgerufen.

// Assumes an open SqlConnection and SqlDataAdapter inside of a using block.
adapter.SelectCommand.CommandText = newQueryString;
builder.RefreshSchema();

dataSet.Tables.Remove(dataSet.Tables[tableName]);
adapter.Fill(dataSet, tableName);

Weitere Informationen: