Generování příkazů s CommandBuilders

SelectCommand Pokud je vlastnost dynamicky zadaná v době běhu, například prostřednictvím nástroje pro dotaz, který přebírá textový příkaz od uživatele, pravděpodobně nebudete moci určit odpovídající InsertCommand, UpdateCommandnebo DeleteCommand v době návrhu. Pokud se DataTable mapy mapují nebo generují z jedné databázové tabulky, můžete využít výhod DbCommandBuilder objektu k automatickému vygenerování objektu DeleteCommand, InsertCommanda UpdateCommand z DbDataAdapter.

Jako minimální požadavek musíte nastavit SelectCommand vlastnost, aby automatické generování příkazů fungovalo. Schéma tabulky načtené SelectCommand vlastností určuje syntaxi automaticky vygenerovaných příkazů INSERT, UPDATE a DELETE.

Musí DbCommandBuilder provést příkazy SelectCommand SQL, aby vrátil metadata potřebná k vytvoření příkazů INSERT, UPDATE a DELETE SQL. V důsledku toho je potřeba provést další cestu ke zdroji dat, což může bránit výkonu. Chcete-li dosáhnout optimálního výkonu, zadejte příkazy explicitně místo použití DbCommandBuilder.

Musí SelectCommand také vrátit aspoň jeden primární klíč nebo jedinečný sloupec. Pokud žádné nejsou k dispozici, InvalidOperation vygeneruje se výjimka a příkazy se negenerují.

Pokud je přidružen k objektu DataAdapter, DbCommandBuilder automaticky vygeneruje UpdateCommandInsertCommand, a DeleteCommand vlastnostiDataAdapter, pokud jsou odkazy null. Pokud již existuje Command pro vlastnost, použije se existující Command .

Zobrazení databáze vytvořená spojením dvou nebo více tabulek dohromady se nepovažují za jednu tabulku databáze. V tomto případě nemůžete použít k automatickému DbCommandBuilder generování příkazů. Musíte zadat příkazy explicitně. Informace o explicitní nastavení příkazů pro překlad aktualizací DataSet zpět do zdroje dat naleznete v tématu Aktualizace zdrojů dat pomocí objektů DataAdapter.

Možná budete chtít namapovat výstupní parametry zpět na aktualizovaný řádek DataSet. Jednou z běžných úloh by bylo načtení hodnoty automaticky generovaného pole identity nebo časového razítka ze zdroje dat. Ve DbCommandBuilder výchozím nastavení se výstupní parametry namapují na sloupce v aktualizovaném řádku. V tomto případě musíte příkaz zadat explicitně. Příklad mapování automaticky vygenerovaného pole identity zpět na sloupec vloženého řádku najdete v tématu Načítání hodnot Identity nebo Automatické číslo.

Pravidla pro automaticky generované příkazy

Následující tabulka ukazuje pravidla pro generování automaticky generovaných příkazů.

Příkaz Pravidlo
InsertCommand Vloží řádek do zdroje dat pro všechny řádky v tabulce s příponou RowStateAdded. Vloží hodnoty pro všechny sloupce, které se dají aktualizovat (ale ne pro sloupce, jako jsou identity, výrazy nebo časové razítko).
UpdateCommand Aktualizace řádky ve zdroji dat pro všechny řádky v tabulce s příponou RowStateModified. Aktualizace hodnoty všech sloupců s výjimkou sloupců, které nelze aktualizovat, jako jsou identity nebo výrazy. Aktualizace všechny řádky, ve kterých hodnoty sloupců ve zdroji dat odpovídají hodnotám sloupce primárního klíče řádku a kde zbývající sloupce ve zdroji dat odpovídají původním hodnotám řádku. Další informace najdete v části Optimistic Concurrency Model for Aktualizace a Deletes (Optimistický model souběžnosti pro Aktualizace a odstranění).
DeleteCommand Odstraní řádky ve zdroji dat pro všechny řádky v tabulce s příponou RowStateDeleted. Odstraní všechny řádky, ve kterých hodnoty sloupců odpovídají hodnotám sloupce primárního klíče řádku a kde zbývající sloupce ve zdroji dat odpovídají původním hodnotám řádku. Další informace najdete v části Optimistic Concurrency Model for Aktualizace a Deletes (Optimistický model souběžnosti pro Aktualizace a odstranění).

Optimistický model souběžnosti pro Aktualizace a odstranění

Logika pro generování příkazů automaticky pro příkazy UPDATE a DELETE je založená na optimistické souběžnosti – to znamená, že záznamy nejsou uzamčeny pro úpravy a mohou je upravovat jiní uživatelé nebo procesy kdykoli. Vzhledem k tomu, že záznam mohl být po vrácení z příkazu SELECT změněn, ale před vydáním příkazu UPDATE nebo DELETE obsahuje automaticky vygenerovaný příkaz UPDATE nebo DELETE klauzuli WHERE, která určuje, že se řádek aktualizuje pouze v případě, že obsahuje všechny původní hodnoty a nebyl odstraněn ze zdroje dat. Tím se zabrání přepsání nových dat. Pokud se automaticky vygenerovaná aktualizace pokusí aktualizovat řádek, který byl odstraněn nebo který neobsahuje původní hodnoty nalezené v nástroji DataSet, příkaz neovlivní žádné záznamy a DBConcurrencyException vyvolá se.

Pokud chcete, aby se funkce UPDATE nebo DELETE dokončila bez ohledu na původní hodnoty, musíte explicitně nastavit UpdateCommand hodnotu pro DataAdapter automatické generování příkazů a nespoléhejte na automatické generování příkazů.

Omezení logiky automatického generování příkazů

Následující omezení platí pro automatické generování příkazů.

Pouze nesouvisející tabulky

Logika automatického generování příkazů generuje příkazy INSERT, UPDATE nebo DELETE pro samostatné tabulky bez zohlednění relací s jinými tabulkami ve zdroji dat. V důsledku toho může dojít k selhání při volání Update odeslat změny pro sloupec, který se účastní omezení cizího klíče v databázi. Pokud se chcete této výjimce vyhnout, nepoužívejte DbCommandBuilder pro aktualizaci sloupců zahrnutých do omezení cizího klíče. Místo toho explicitně zadejte příkazy použité k provedení operace.

Názvy tabulek a sloupců

Logika automatického generování příkazů může selhat, pokud názvy sloupců nebo názvů tabulek obsahují speciální znaky, jako jsou mezery, tečky, uvozovky nebo jiné neosamocené znaky, i když jsou oddělené hranatými závorkami. V závislosti na poskytovateli může nastavení parametrů QuotePrefix a QuoteSuffix povolit logiku generování zpracovat mezery, ale nemůže uvozovat speciální znaky. Podporují se plně kvalifikované názvy tabulek ve formátu catalog.schema.table .

Použití CommandBuilderu k automatickému vygenerování příkazu SQL

Chcete-li automaticky generovat příkazy SQL pro , DataAdapternejprve nastavte SelectCommand vlastnost DataAdapter, pak vytvořte CommandBuilder objekt a zadejte jako argument DataAdapter , pro který CommandBuilder bude automaticky generovat příkazy SQL.

' 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 = "]";  

Úprava příkazu SelectCommand

Pokud změníte CommandText příkazy SelectCommand INSERT, UPDATE nebo DELETE automaticky vygenerované, může dojít k výjimce. Pokud změněné SelectCommand.CommandText obsahuje informace o schématu, které jsou nekonzistentní s SelectCommand.CommandText použitými příkazy při vložení, aktualizaci nebo odstranění byly automaticky generovány, budoucí volání DataAdapter.Update metody se mohou pokusit o přístup ke sloupcům, které již neexistují v aktuální tabulce odkazované SelectCommandsadou , a vyvolá se výjimka.

Informace o schématu používané CommandBuilder k automatickému generování příkazů můžete aktualizovat voláním RefreshSchema metody CommandBuilder.

Pokud chcete zjistit, jaký příkaz se automaticky vygeneroval, můžete získat odkaz na automaticky generované příkazy pomocí GetInsertCommand, GetUpdateCommanda GetDeleteCommand metody objektu CommandBuilder a kontrolu CommandText vlastnosti přidruženého příkazu.

Následující příklad kódu zapíše do konzoly příkaz update, který se automaticky vygeneroval.

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

Následující příklad znovu vytvoří Customers tabulku v custDS datové sadě. Metoda RefreshSchema se volá k aktualizaci automaticky generovaných příkazů s informacemi o tomto novém sloupci.

' 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");  

Viz také