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
, UpdateCommand
nebo 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
, InsertCommand
a 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 UpdateCommand
InsertCommand
, 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 RowState Added. 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 RowState Modified. 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 RowState Deleted. 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 , DataAdapter
nejprve 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é SelectCommand
sadou , 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
, GetUpdateCommand
a 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");