Implementace optimistického řízení souběžnosti ovládacím prvkem SqlDataSource (VB)
V tomto kurzu si projdeme základy optimistického řízení souběžnosti a pak prozkoumáme, jak ho implementovat pomocí ovládacího prvku SqlDataSource.
Úvod
V předchozím kurzu jsme prozkoumali, jak do ovládacího prvku SqlDataSource přidat možnosti vkládání, aktualizace a odstraňování. Stručně řečeno, abychom mohli tyto funkce poskytnout, potřebovali jsme zadat odpovídající INSERT
příkazy , UPDATE
nebo DELETE
SQL ve vlastnostech ovládacích prvků UpdateCommand
InsertCommand
, nebo DeleteCommand
spolu s příslušnými parametry v InsertParameters
kolekcích , UpdateParameters
a DeleteParameters
. I když tyto vlastnosti a kolekce lze zadat ručně, tlačítko Průvodce konfigurací zdroje dat s tlačítkem Upřesnit nabízí zaškrtávací políčko Generovat INSERT
příkazy , UPDATE
a DELETE
, které automaticky vytvoří tyto příkazy na SELECT
základě příkazu .
Kromě zaškrtávacího políčka Generovat INSERT
příkazy , UPDATE
a DELETE
obsahuje dialogové okno Rozšířené možnosti generování SQL možnost Použít optimistickou souběžnost (viz Obrázek 1). Pokud je tato možnost zaškrtnutá WHERE
, klauzule v automaticky vygenerovaných UPDATE
příkazech a DELETE
se upraví tak, aby provedly aktualizaci nebo odstranění pouze v případě, že se podkladová data databáze od posledního načtení dat uživatelem do mřížky nezměnila.
Obrázek 1: Podporu optimistické souběžnosti můžete přidat v dialogovém okně Rozšířené možnosti generování SQL.
V kurzu Implementace optimistické souběžnosti jsme prozkoumali základy řízení optimistické souběžnosti a jeho přidání do objektu ObjectDataSource. V tomto kurzu se podíváme na základy optimistického řízení souběžnosti a pak prozkoumáme, jak ho implementovat pomocí sqldatasource.
Rekapitulace optimistické souběžnosti
U webových aplikací, které umožňují více souběžným uživatelům upravovat nebo odstraňovat stejná data, existuje možnost, že jeden uživatel nechtěně přepíše jiného uživatele. V kurzu Implementace optimistické souběžnosti jsem uvedl následující příklad:
Představte si, že dva uživatelé, Jisun a Sam, navštívili stránku v aplikaci, která návštěvníkům umožňovala aktualizovat a odstraňovat produkty prostřednictvím ovládacího prvku GridView. Oba kliknou na tlačítko Upravit pro Chai přibližně ve stejnou dobu. Jisun změní název produktu na Chai Tea a klikne na tlačítko Aktualizovat. Čistý výsledek je příkaz UPDATE
, který se odešle do databáze, který nastaví všechna aktualizovatelná pole produktu (i když Jisun aktualizoval pouze jedno pole , ProductName
). V tomto okamžiku má databáze pro tento konkrétní produkt hodnoty Chai Čaj, kategorii Nápoje, dodavatele Exotic Liquids atd. Na obrazovce GridView na sam s však stále zobrazuje název produktu v upravitelném řádku GridView jako Chai. Několik sekund po potvrzení změn jisun sam aktualizuje kategorii na Condiments a klikne na Aktualizovat. Výsledkem je UPDATE
příkaz odeslaný do databáze, který nastaví název produktu na Chai, CategoryID
na odpovídající ID kategorie Condiments atd. Změny jisunu v názvu produktu byly přepsány.
Tuto interakci znázorňuje obrázek 2.
Obrázek 2: Když dva uživatelé současně aktualizují záznam, existuje potenciál pro jednoho uživatele změny k přepsání ostatních (kliknutím zobrazíte obrázek v plné velikosti)
Aby se zabránilo tomuto scénáři, musí být implementována forma řízení souběžnosti . Optimistická souběžnost , na kterou se tento kurz zaměřuje, vychází z předpokladu, že i když občas může docházet ke konfliktům souběžnosti, v drtivé většině případů k takovým konfliktům nedojde. Proto pokud dojde ke konfliktu, optimistické řízení souběžnosti jednoduše informuje uživatele, že jeho změny nelze uložit, protože jiný uživatel upravil stejná data.
Poznámka
U aplikací, u kterých se předpokládá, že dojde k mnoha konfliktům souběžnosti, nebo pokud takové konflikty nejsou přípustné, je možné místo toho použít pesimistické řízení souběžnosti. Podrobnější diskuzi o pesimistickém řízení souběžnosti najdete v kurzu Implementace optimistické souběžnosti.
Řízení optimistické souběžnosti funguje tak, že zajišťuje, aby aktualizovaný nebo odstraněný záznam měl stejné hodnoty jako při spuštění procesu aktualizace nebo odstranění. Když například kliknete na tlačítko Upravit v upravitelném objektu GridView, hodnoty záznamů se načtou z databáze a zobrazí se v textových polích a dalších webových ovládacích prvcích. Tyto původní hodnoty jsou uloženy GridView. Později poté, co uživatel provede změny a klikne na tlačítko Aktualizovat, UPDATE
musí použitý příkaz vzít v úvahu původní hodnoty a nové hodnoty a aktualizovat podkladový databázový záznam pouze v případě, že původní hodnoty, které uživatel začal upravovat, jsou identické s hodnotami, které jsou stále v databázi. Obrázek 3 znázorňuje tuto posloupnost událostí.
Obrázek 3: Aby aktualizace nebo odstranění proběhly úspěšně, původní hodnoty musí být stejné jako aktuální hodnoty databáze (kliknutím zobrazíte obrázek v plné velikosti)
Existují různé přístupy k implementaci optimistické souběžnosti (podívejte se na několik možností v článku Logika aktualizace optimistické souběžnostiPetera A. Bromberga). Technika, kterou používá SqlDataSource (stejně jako ADO.NET Typed DataSets používané v naší vrstvě přístupu k datůmWHERE
) rozšiřuje klauzuli tak, aby zahrnovala porovnání všech původních hodnot. Následující UPDATE
příkaz například aktualizuje název a cenu produktu pouze v případě, že aktuální hodnoty databáze jsou rovny hodnotám, které byly původně načteny při aktualizaci záznamu v GridView. Parametry @ProductName
a @UnitPrice
obsahují nové hodnoty zadané uživatelem, zatímco @original_ProductName
a @original_UnitPrice
obsahují hodnoty, které byly původně načteny do GridView při kliknutí na tlačítko Upravit:
UPDATE Products SET
ProductName = @ProductName,
UnitPrice = @UnitPrice
WHERE
ProductID = @original_ProductID AND
ProductName = @original_ProductName AND
UnitPrice = @original_UnitPrice
Jak uvidíme v tomto kurzu, povolení optimistického řízení souběžnosti pomocí SqlDataSource je stejně jednoduché jako zaškrtnutí políčka.
Krok 1: Vytvoření zdroje dat Sql, který podporuje optimistickou souběžnost
Začněte otevřením OptimisticConcurrency.aspx
stránky ze SqlDataSource
složky . Přetáhněte ovládací prvek SqlDataSource z panelu nástrojů na Designer a jeho vlastnost na ProductsDataSourceWithOptimisticConcurrency
hodnotu ID
. Potom klikněte na odkaz Konfigurovat zdroj dat z inteligentní značky ovládacího prvku. Na první obrazovce průvodce zvolte, jestli chcete pracovat s NORTHWINDConnectionString
a klikněte na Další.
Obrázek 4: Volba pro práci s NORTHWINDConnectionString
(kliknutím zobrazíte obrázek v plné velikosti)
V tomto příkladu přidáme GridView, který uživatelům umožní upravovat Products
tabulku. Proto na obrazovce Konfigurovat příkaz Select zvolte Products
tabulku z rozevíracího seznamu a vyberte ProductID
sloupce , ProductName
, UnitPrice
a Discontinued
, jak je znázorněno na obrázku 5.
Obrázek 5: Z Products
tabulky vraťte ProductID
sloupce , ProductName
, UnitPrice
a Discontinued
(kliknutím zobrazíte obrázek v plné velikosti)
Po výběru sloupců kliknutím na tlačítko Upřesnit zobrazte dialogové okno Rozšířené možnosti generování SQL. Zaškrtněte políčka Generovat INSERT
příkazy , UPDATE
a DELETE
a Použít optimistickou souběžnost a klikněte na OK (snímek obrazovky najdete na obrázku 1). Dokončete průvodce kliknutím na Další a pak na Dokončit.
Po dokončení průvodce Konfigurací zdroje dat se chvíli podívejte na výsledné DeleteCommand
vlastnosti a UpdateCommand
DeleteParameters
kolekce a UpdateParameters
. Nejjednodušší způsob, jak to udělat, je kliknout na kartu Zdroj v levém dolním rohu a zobrazit deklarativní syntaxi stránky. Tady najdete UpdateCommand
hodnotu:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
[UnitPrice] = @original_UnitPrice AND
[Discontinued] = @original_Discontinued
Se sedmi parametry v kolekci UpdateParameters
:
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
runat="server" ...>
<DeleteParameters>
...
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ProductName" Type="String" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Discontinued" Type="Boolean" />
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</UpdateParameters>
...
</asp:SqlDataSource>
Podobně DeleteCommand
by vlastnost a DeleteParameters
kolekce měly vypadat takto:
DELETE FROM [Products]
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
[UnitPrice] = @original_UnitPrice AND
[Discontinued] = @original_Discontinued
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
runat="server" ...>
<DeleteParameters>
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</DeleteParameters>
<UpdateParameters>
...
</UpdateParameters>
...
</asp:SqlDataSource>
Kromě rozšíření WHERE
klauzulí UpdateCommand
vlastností a DeleteCommand
(a přidání dalších parametrů do příslušných kolekcí parametrů) upravíte výběrem možnosti Použít optimistickou souběžnost dvě další vlastnosti:
ConflictDetection
Změní vlastnost zOverwriteChanges
(výchozí) naCompareAllValues
OldValuesParameterFormatString
Změní vlastnost z {0} (výchozí) na original_{0} .
Když datový web ovládací prvek vyvolá SqlDataSource s Update()
nebo Delete()
metodu, předá původní hodnoty. Pokud je vlastnost SqlDataSource s nastavená ConflictDetection
na CompareAllValues
hodnotu , přidají se do příkazu tyto původní hodnoty. Vlastnost OldValuesParameterFormatString
poskytuje vzor pojmenování použitý pro tyto parametry původní hodnoty. Průvodce konfigurovat zdroj dat používá original_{0} a pojmenuje každý původní parametr ve UpdateCommand
vlastnostech UpdateParameters
a kolekcích a DeleteParameters
DeleteCommand
odpovídajícím způsobem.
Poznámka
Vzhledem k tomu, že nepoužíváme možnosti vkládání ovládacích prvků SqlDataSource, můžete odebrat vlastnost a její InsertParameters
kolekciInsertCommand
.
Správné zpracováníNULL
hodnot
Rozšířené UPDATE
příkazy a DELETE
automaticky generované průvodcem Konfigurovat zdroj dat při použití optimistické souběžnosti bohužel nefungují se záznamy, které obsahují NULL
hodnoty. Pokud chcete zjistit proč, zvažte naše služby SqlDataSource UpdateCommand
:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
[UnitPrice] = @original_UnitPrice AND
[Discontinued] = @original_Discontinued
Sloupec UnitPrice
v tabulce Products
může obsahovat NULL
hodnoty. Pokud má NULL
konkrétní záznam hodnotu pro UnitPrice
, WHERE
část [UnitPrice] = @original_UnitPrice
klauzule se vždy vyhodnotí jako False, protože NULL = NULL
vždy vrátí hodnotu False. Záznamy NULL
obsahující hodnoty proto nelze upravovat ani odstraňovat, protože UPDATE
klauzule příkazů a DELETE
nevrátí žádné řádky WHERE
pro aktualizaci nebo odstranění.
Poznámka
Tato chyba byla společnosti Microsoft poprvé oznámena v červnu 2004 v tématu SqlDataSource Generuje nesprávné příkazy SQL a je údajně naplánováno, aby byla opravena v příští verzi ASP.NET.
Abychom tento problém vyřešili, musíme ručně aktualizovat WHERE
klauzule ve vlastnostech a UpdateCommand
DeleteCommand
pro všechny sloupce, které můžou mít NULL
hodnoty. Obecně platí, že změňte [ColumnName] = @original_ColumnName
na:
(
([ColumnName] IS NULL AND @original_ColumnName IS NULL)
OR
([ColumnName] = @original_ColumnName)
)
Tuto úpravu lze provést přímo prostřednictvím deklarativního kódu, prostřednictvím možností UpdateQuery nebo DeleteQuery z okno Vlastnosti nebo prostřednictvím karet UPDATE a DELETE v možnosti Zadat vlastní příkaz SQL nebo uloženou proceduru v průvodci Konfigurovat zdroj dat. Tato změna musí být provedena pro každý sloupec v klauzuli UpdateCommand
a DeleteCommand
s WHERE
, který může obsahovat NULL
hodnoty.
Použití tohoto v našem příkladu má za následek následující změněné UpdateCommand
hodnoty a DeleteCommand
:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
(([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice)) AND
[Discontinued] = @original_Discontinued
DELETE FROM [Products]
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
(([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice)) AND
[Discontinued] = @original_Discontinued
Krok 2: Přidání objektu GridView s možnostmi upravit a odstranit
SqlDataSource nakonfigurovaný tak, aby podporoval optimistickou souběžnost, zbývá jen přidat datový webový ovládací prvek na stránku, která využívá tento ovládací prvek souběžnosti. Pro účely tohoto kurzu přidáme Objekt GridView, který poskytuje funkce pro úpravy i odstranění. Chcete-li toho dosáhnout, přetáhněte objekt GridView z panelu nástrojů do Designer a nastavte jeho ID
na Products
. Z inteligentní značky GridView vytvořte vazbu na ProductsDataSourceWithOptimisticConcurrency
ovládací prvek SqlDataSource přidaný v kroku 1. Nakonec zaškrtněte možnosti Povolit úpravy a Povolit odstranění z inteligentní značky.
Obrázek 6: Vytvoření vazby objektu GridView na SqlDataSource a povolení úprav a odstranění (kliknutím zobrazíte obrázek v plné velikosti)
Po přidání objektu GridView nakonfigurujte jeho vzhled odebráním ProductID
BoundField, změnou ProductName
vlastnosti BoundField s HeaderText
na Product a aktualizací UnitPrice
BoundField tak, aby jeho HeaderText
vlastnost byla jednoduše Price. V ideálním případě bychom vylepšili rozhraní pro úpravy tak, aby obsahovalo RequiredFieldValidator pro ProductName
hodnotu a CompareValidator pro UnitPrice
hodnotu (aby se zajistilo, že se jedná o správně naformátovanou číselnou hodnotu). Podrobnější informace o přizpůsobení rozhraní pro úpravy gridview najdete v kurzu Přizpůsobení rozhraní pro úpravu dat .
Poznámka
Stav zobrazení GridView s musí být povolen, protože původní hodnoty předané z Objekt GridView do SqlDataSource jsou uloženy ve stavu zobrazení.
Po provedení těchto úprav objektu GridView by deklarativní značky GridView a SqlDataSource měly vypadat podobně jako následující:
<asp:SqlDataSource ID="ProductsDataSourceWithOptimisticConcurrency"
runat="server" ConflictDetection="CompareAllValues"
ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
DeleteCommand=
"DELETE FROM [Products]
WHERE [ProductID] = @original_ProductID
AND [ProductName] = @original_ProductName
AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice))
AND [Discontinued] = @original_Discontinued"
OldValuesParameterFormatString=
"original_{0}"
SelectCommand=
"SELECT [ProductID], [ProductName], [UnitPrice], [Discontinued]
FROM [Products]"
UpdateCommand=
"UPDATE [Products]
SET [ProductName] = @ProductName, [UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE [ProductID] = @original_ProductID
AND [ProductName] = @original_ProductName
AND (([UnitPrice] IS NULL AND @original_UnitPrice IS NULL)
OR ([UnitPrice] = @original_UnitPrice))
AND [Discontinued] = @original_Discontinued">
<DeleteParameters>
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</DeleteParameters>
<UpdateParameters>
<asp:Parameter Name="ProductName" Type="String" />
<asp:Parameter Name="UnitPrice" Type="Decimal" />
<asp:Parameter Name="Discontinued" Type="Boolean" />
<asp:Parameter Name="original_ProductID" Type="Int32" />
<asp:Parameter Name="original_ProductName" Type="String" />
<asp:Parameter Name="original_UnitPrice" Type="Decimal" />
<asp:Parameter Name="original_Discontinued" Type="Boolean" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="Products" runat="server"
AutoGenerateColumns="False" DataKeyNames="ProductID"
DataSourceID="ProductsDataSourceWithOptimisticConcurrency">
<Columns>
<asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="UnitPrice" HeaderText="Price"
SortExpression="UnitPrice" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
</Columns>
</asp:GridView>
Pokud chcete zobrazit ovládací prvek optimistické souběžnosti v akci, otevřete dvě okna prohlížeče a načtěte OptimisticConcurrency.aspx
stránku v obou. Klikněte na tlačítka Upravit u prvního produktu v obou prohlížečích. V jednom prohlížeči změňte název produktu a klikněte na Aktualizovat. Prohlížeč se vrátí zpět a GridView se vrátí do režimu před úpravami a zobrazí nový název produktu právě upraveného záznamu.
V druhém okně prohlížeče změňte cenu (ale ponechte název produktu jako původní hodnotu) a klikněte na Aktualizovat. Při postbacku se mřížka vrátí do režimu před úpravami, ale změna ceny se nezaznamená. Ve druhém prohlížeči se zobrazí stejná hodnota jako u prvního názvu nového produktu se starou cenou. Změny provedené v druhém okně prohlížeče byly ztraceny. Změny se navíc ztratily poměrně tiše, protože se nenašla žádná výjimka nebo zpráva, které by naznačovaly, že právě došlo k narušení souběžnosti.
Obrázek 7: Změny v druhém okně prohlížeče byly bezobslužně ztraceny (kliknutím zobrazíte obrázek v plné velikosti)
Důvodem, proč nebyly potvrzeny druhé změny prohlížeče, bylo to, že UPDATE
klauzule s příkazu WHERE
vyfiltrovala všechny záznamy, a proto neovlivnila žádné řádky. Podívejme se znovu na UPDATE
příkaz:
UPDATE [Products] SET
[ProductName] = @ProductName,
[UnitPrice] = @UnitPrice,
[Discontinued] = @Discontinued
WHERE
[ProductID] = @original_ProductID AND
[ProductName] = @original_ProductName AND
(([UnitPrice] IS NULL AND @original_UnitPrice IS NULL) OR
([UnitPrice] = @original_UnitPrice)) AND
[Discontinued] = @original_Discontinued
Když druhé okno prohlížeče aktualizuje záznam, původní název produktu zadaný v WHERE
klauzuli neodpovídá existujícímu názvu produktu (protože ho změnil první prohlížeč). [ProductName] = @original_ProductName
Příkaz proto vrátí hodnotu False a nemá vliv na UPDATE
žádné záznamy.
Poznámka
Odstranění funguje stejným způsobem. Když jsou otevřená dvě okna prohlížeče, začněte úpravou daného produktu v jednom a uložením jeho změn. Po uložení změn v jednom prohlížeči klikněte na tlačítko Odstranit pro stejný produkt v druhém prohlížeči. Vzhledem k tomu, že původní hodnoty se neshodovaly v klauzuli DELETE
s příkazu WHERE
, odstranění bezobslužně selže.
Z pohledu koncového uživatele v druhém okně prohlížeče se po kliknutí na tlačítko Aktualizovat mřížka vrátí do režimu před úpravami, ale jejich změny byly ztraceny. Neexistuje ale žádná vizuální zpětná vazba, že se jejich změny nelepily. V ideálním případě platí, že pokud dojde ke ztrátě změn uživatele kvůli narušení souběžnosti, upozorníme ho a třeba mřížku ponecháme v režimu úprav. Pojďme se podívat, jak toho dosáhnout.
Krok 3: Určení, kdy došlo k narušení souběžnosti
Vzhledem k tomu, že porušení souběžnosti odmítne provedené změny, bylo by vhodné upozornit uživatele, když dojde k narušení souběžnosti. Chcete-li uživatele upozornit, přidejte do horní části stránky ovládací prvek Label Web, ConcurrencyViolationMessage
jehož Text
vlastnost zobrazí následující zprávu: Pokusili jste se aktualizovat nebo odstranit záznam, který byl současně aktualizován jiným uživatelem. Zkontrolujte změny jiného uživatele a pak aktualizaci zopakujte nebo odstraňte. Nastavte vlastnost ovládacího prvku Popisek na CssClass
Warning, což je třída CSS definovaná v Styles.css
, která zobrazuje text červeným, kurzívou, tučným a velkým písmem. Nakonec nastavte vlastnosti Popisky Visible
a EnableViewState
na False
hodnotu . Tím se popisek skryje s výjimkou pouze těch, u kterých jsme explicitně nastavili jeho Visible
vlastnost na True
.
Obrázek 8: Přidání ovládacího prvku Popisek na stránku pro zobrazení upozornění (kliknutím zobrazíte obrázek v plné velikosti)
Při provádění aktualizace nebo odstranění se objekty GridView RowUpdated
a RowDeleted
obslužné rutiny událostí aktivují poté, co jeho ovládací prvek zdroje dat provedl požadovanou aktualizaci nebo odstranění. Z těchto obslužných rutin událostí můžeme určit, kolik řádků bylo touto operací ovlivněno. Pokud by to ovlivnilo nula řádků, chceme zobrazit ConcurrencyViolationMessage
popisek.
Vytvořte obslužnou rutinu RowUpdated
události pro události a RowDeleted
a přidejte následující kód:
Protected Sub Products_RowUpdated(sender As Object, e As GridViewUpdatedEventArgs) _
Handles Products.RowUpdated
If e.AffectedRows = 0 Then
ConcurrencyViolationMessage.Visible = True
e.KeepInEditMode = True
' Rebind the data to the GridView to show the latest changes
Products.DataBind()
End If
End Sub
Protected Sub Products_RowDeleted(sender As Object, e As GridViewDeletedEventArgs) _
Handles Products.RowDeleted
If e.AffectedRows = 0 Then
ConcurrencyViolationMessage.Visible = True
End If
End Sub
V obou obslužných rutinách událostí zkontrolujeme e.AffectedRows
vlastnost a pokud se rovná 0, nastavte ConcurrencyViolationMessage
vlastnost Popisek na True
Visible
. V obslužné rutině RowUpdated
události také dáváme objektu GridView pokyn, aby zůstal v režimu úprav nastavením KeepInEditMode
vlastnosti true. Přitom musíme data znovu připojit k mřížce, aby se data ostatních uživatelů načetla do rozhraní pro úpravy. Toho je dosaženo voláním metody GridView s DataBind()
.
Jak ukazuje obrázek 9, u těchto dvou obslužných rutin událostí se při každém porušení souběžnosti zobrazí velmi nápadná zpráva.
Obrázek 9: Zpráva je zobrazena v obličeji porušení souběžnosti (kliknutím zobrazíte obrázek v plné velikosti)
Souhrn
Při vytváření webové aplikace, ve které může stejná data upravovat více souběžných uživatelů, je důležité zvážit možnosti řízení souběžnosti. Ve výchozím nastavení webové ovládací prvky ASP.NET dat a ovládací prvky zdroje dat nepoužívají žádné řízení souběžnosti. Jak jsme viděli v tomto kurzu, implementace optimistického řízení souběžnosti pomocí SqlDataSource je poměrně rychlá a snadná. SqlDataSource zpracovává většinu legwork pro přidání rozšířených WHERE
klauzulí do automaticky vygenerovaných UPDATE
a příkazů, DELETE
ale existuje několik jemností ve zpracování NULL
sloupců hodnot, jak je popsáno v části Správné zpracování NULL
hodnot.
Tento kurz zakončí naše zkoumání SqlDataSource. Zbývající kurzy se vrátí k práci s daty pomocí ObjectDataSource a vrstvené architektury.
Šťastné programování!
O autorovi
Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho najít na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na http://ScottOnWriting.NETadrese .