Sdílet prostřednictvím


Implementace optimistického řízení souběžnosti ovládacím prvkem SqlDataSource (VB)

od Scotta Mitchella

Stáhnout PDF

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 poskytnout tyto funkce, potřebovali jsme ve vlastnostech ovládacího prvku určit odpovídající příkaz SQL INSERT, UPDATE nebo DELETE spolu s příslušnými parametry v kolekcích InsertParameters, UpdateParameters a DeleteParameters. I když je možné tyto vlastnosti a kolekce zadat ručně, průvodce Konfigurovat zdroj dat tlačítkem Upřesnit nabízí zaškrtávací políčko Generovat INSERT, UPDATE, a DELETE příkazy, které automaticky vytvoří tyto příkazy založené na příkazu SELECT.

Kromě zaškrtávacího políčka Generovat INSERT, UPDATE a DELETE příkazy obsahuje dialogové okno Pokročilé možnosti generování SQL volbu Používat optimistickou souběžnost (viz obrázek 1). Když je zaškrtnuto, klauzule v automaticky vygenerovaných UPDATE a DELETE příkazech se upraví tak, aby prováděly pouze aktualizaci nebo odstranění, pokud se podkladová data databáze od posledního načtení dat uživatelem do mřížky nezměnila.

Podporu optimistické souběžnosti můžete přidat prostřednictvím dialogového okna Upřesnit možnosti generování SQL.

Obrázek 1: Podporu optimistické souběžnosti můžete přidat pomocí dialogového okna Pokročilé možnosti generování SQL

Zpátky v kurzu Implementace optimistické souběžnosti jsme prozkoumali základy optimistického řízení souběžnosti a jak ho přidat do ObjectDataSource. V tomto kurzu si probereme 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 může omylem přepsat jiné změny. V tutoriálu Implementace optimistické souběžnosti jsem poskytl 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žnila aktualizovat a odstranit produkty prostřednictvím ovládacího prvku GridView. Oba ve stejnou dobu kliknou na tlačítko Upravit pro Chai. Jisun změní název produktu na Chai Tea a klikne na tlačítko Aktualizovat. Čistý výsledek je UPDATE příkaz odeslaný 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 hodnoty Chai Tea, kategorii Nápoje, dodavatele Exotic Liquids a tak dále pro tento konkrétní produkt. GridView na Samově obrazovce ale stále zobrazuje název produktu v řádku GridView, který lze upravovat, jako Chai. Několik sekund po provedení změn Jisunu Sam aktualizuje kategorii na dochucovadla 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 Koření a tak dále. Změny, které Jisun provedla v názvu produktu, byly přepsány.

Obrázek 2 znázorňuje tuto interakci.

Když dva uživatelé současně aktualizují záznam, existuje potenciál, že změny jednoho uživatele přepíší změny druhého

Obrázek 2: Když dva uživatelé současně aktualizují záznam, může dojít ke změně jednoho uživatele, aby přepsal ostatní (kliknutím zobrazíte obrázek v plné velikosti).

Aby k tomuto scénáři nedošlo, musí být implementována forma řízení souběžnosti. Optimistická souběžnost, na kterou se tento tutoriál zaměřuje, funguje na předpokladu, že i když může čas od času dojít ke konfliktům souběžnosti, ve velké 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 jejich změny nelze uložit, protože jiný uživatel změnil 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é, můžete 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 .

Optimistické řízení souběžnosti funguje tak, že zajišťuje, aby záznam, který se aktualizuje nebo odstranil, měl stejné hodnoty jako při spuštění aktualizace nebo odstranění procesu. Když například kliknete na tlačítko Upravit v upravitelném objektu GridView, hodnoty záznamů se č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 objektem GridView. Později, když uživatel provede změny a klikne na tlačítko Aktualizovat, musí použitý příkaz vzít v úvahu původní hodnoty a nové hodnoty a aktualizovat pouze podkladový záznam databáze, pokud původní hodnoty, které uživatel začal upravovat, UPDATE jsou stejné jako hodnoty stále v databázi. Obrázek 3 znázorňuje tuto posloupnost událostí.

Aby aktualizace nebo odstranění proběhly úspěšně, musí být původní hodnoty rovny aktuálním hodnotám databáze.

Obrázek 3: Aby aktualizace nebo odstranění byla úspěšná, musí být původní hodnoty rovny aktuálním hodnotám databáze (kliknutím zobrazíte obrázek v plné velikosti).

Existují různé přístupy k implementaci optimistické souběžnosti (viz Peter A. Bromberg's logika aktualizace optimistické souběžnosti pro stručné seznámení s řadou možností). Technika používaná SqlDataSource (a také ADO.NET Typové datové sady používané v naší vrstvě přístupu k datům) rozšiřuje WHERE 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 se aktuální hodnoty databáze rovnají 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 po 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í SqlDataSource, 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ů do Návrháře a nastavte jeho vlastnost ID na ProductsDataSourceWithOptimisticConcurrency. Klikněte na odkaz Konfigurovat zdroj dat pomocí inteligentní značky ovládacího prvku. Na první obrazovce v průvodci zvolte, že chcete pracovat s NORTHWINDConnectionString a klikněte na Další.

Vyberte práci s NORTHWINDConnectionString

Obrázek 4: Volba práce s obrázkem NORTHWINDConnectionString (kliknutím zobrazíte obrázek s plnou velikostí)

V tomto příkladu přidáme Objekt GridView, který uživatelům umožní tabulku upravit Products . Proto na obrazovce Konfigurovat příkaz select zvolte Products tabulku z rozevíracího seznamu a vyberte ProductID, ProductName, UnitPricea Discontinued sloupce, jak je znázorněno na obrázku 5.

Z tabulky Produkty vrátit sloupce ID produktu, Název produktu, Cena jednotky a Ukončeno.

Obrázek 5: Z Products tabulky vraťte sloupce ProductID, 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 zobrazíte dialogové okno Upřesnit možnosti generování SQL. Zaškrtněte políčka pro generování příkazů INSERT, UPDATE a DELETE a pro používání optimistické souběžnosti a klikněte na OK (pro snímek obrazovky se vraťte k obrázku 1). Dokončete průvodce kliknutím na Další a poté na Dokončit.

Po dokončení průvodce konfigurací zdroje dat věnujte chvíli kontrole výsledných DeleteCommand a UpdateCommand vlastností a DeleteParameters a UpdateParameters kolekcí. Nejjednodušší způsob, jak to udělat, je kliknout na kartu Zdroj v levém dolním rohu a zobrazit deklarativní syntaxi stránky. Tam 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

S kolekcí UpdateParameters obsahující sedm parametrů:

<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ě by DeleteCommand 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 a DeleteCommand vlastností (a přidání dalších parametrů do příslušných kolekcí parametrů) se výběrem možnosti Použít optimistickou souběžnost upraví dvě další vlastnosti:

Když datový webový ovládací prvek vyvolá SqlDataSource s Update() nebo Delete() metodu, předá původní hodnoty. Pokud je vlastnost SqlDataSource ConflictDetection nastavena na CompareAllValues, tyto původní hodnoty jsou přidány do příkazu. Vlastnost OldValuesParameterFormatString poskytuje vzor pojmenování použitý pro tyto původní parametry hodnoty. Průvodce konfigurací zdroje dat používá original_{0} a pojmenuje každý původní parametr v UpdateCommand a DeleteCommand vlastnostech a UpdateParameters a DeleteParameters kolekcích.

Poznámka:

Protože nepoužíváme možnosti vkládání ovládacího prvku SqlDataSource, můžete odstranit vlastnost InsertCommand a její kolekci InsertParameters.

Správné zpracováníNULLhodnot

Bohužel rozšířené příkazy UPDATE a DELETE, které automaticky vygeneroval průvodce Konfigurovat zdroj dat při použití optimistické souběžnosti, nefungují se záznamy, které obsahují NULL hodnoty. Pokud chcete zjistit proč, zvažte naše SqlDataSource s 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 Products tabulce může obsahovat NULL hodnoty. Pokud má konkrétní záznam NULL hodnotu UnitPrice, WHERE část [UnitPrice] = @original_UnitPrice klauzule se vždy vyhodnotí jako False, protože NULL = NULL vždy vrátí hodnotu False. Proto záznamy obsahující NULL hodnoty nelze upravovat ani odstraňovat, protože UPDATE klauzule a DELETE klauzule příkazů nevrací žádné řádky WHERE pro aktualizaci nebo odstranění.

Poznámka:

Tato chyba byla poprvé hlášena společnosti Microsoft v červnu 2004 v SqlDataSource Generuje nesprávné příkazy SQL a je hlášena, že je naplánována na opravení v další verzi ASP.NET.

Abychom to vyřešili, musíme ručně aktualizovat WHERE klauzule ve vlastnostech UpdateCommand a DeleteCommand pro všechny sloupce, které můžou mít NULL hodnoty. Obecně platí, že změníte [ColumnName] = @original_ColumnName na:

(
   ([ColumnName] IS NULL AND @original_ColumnName IS NULL)
     OR
   ([ColumnName] = @original_ColumnName)
)

Tuto změnu lze provést přímo prostřednictvím deklarativního kódu, prostřednictvím možností UpdateQuery nebo DeleteQuery z okna Vlastnosti nebo prostřednictvím karet UPDATE a DELETE v okně Zadat vlastní příkaz SQL nebo uloženou proceduru v průvodci konfigurací zdroje dat. Tato změna musí být provedena pro každý sloupec v klauzuli UpdateCommand a DeleteCommand s WHERE, které mohou obsahovat NULL hodnoty.

Použití tohoto příkladu má za následek následující změněné UpdateCommand hodnoty a DeleteCommand hodnoty:

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

Když je SqlDataSource nakonfigurovaný tak, aby podporoval optimistickou souběžnost, zbývá už jen přidat webový datový ovládací prvek na stránku, která využívá toto řízení souběžnosti. Pro účely tohoto kurzu přidáme GridView, který poskytuje funkce pro úpravy i odstranění. Chcete-li toho dosáhnout, přetáhněte Objekt GridView ze sady nástrojů do Návrháře a nastavte jej ID na Products. Z inteligentní značky GridView ho 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.

Vytvoření vazby Objektu GridView k SqlDataSource a povolení úprav a odstranění

Obrázek 6: Vytvoření vazby Objektu GridView k SqlDataSource a povolení úprav a odstranění (kliknutím zobrazíte obrázek s plnou velikostí)

Po přidání GridView nakonfigurujte jeho vzhled odebráním ProductID BoundField, změnou vlastnosti ProductName BoundField na Product a aktualizací UnitPrice BoundField tak, aby jeho vlastnost byla jednoduše Price. V ideálním případě bychom vylepšili rozhraní pro úpravy tak, aby zahrnovalo RequiredFieldValidator pro ProductName hodnotu a CompareValidator pro UnitPrice hodnotu (aby se zajistilo, že se jedná o správně formátovanou číselnou hodnotu). Podrobnější informace o přizpůsobení rozhraní pro úpravy dat najdete v kurzu Přizpůsobení rozhraní pro úpravy dat .

Poznámka:

Stav zobrazení GridView s musí být povolen, protože původní hodnoty předané z GridView do SqlDataSource jsou uloženy ve stavu zobrazení.

Po provedení těchto úprav objektu GridView by deklarativní kód GridView a SqlDataSource měl vypadat přibližně takto:

<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 vidět optimistické řízení souběžnosti v akci, otevřete dvě okna prohlížeče a načtěte OptimisticConcurrency.aspx stránku v obou dvou. V obou prohlížečích klikněte na tlačítka Upravit první produkt. V jednom prohlížeči změňte název produktu a klikněte na Aktualizovat. Prohlížeč provede postback a GridView se vrátí do režimu před úpravami, zobrazí nový název produktu pro právě upravený záznam.

V druhém okně prohlížeče změňte cenu (ale ponechte název produktu jako původní hodnotu) a klikněte na Tlačítko Aktualizovat. Při zpětném odeslání se mřížka přepne zpět do režimu před úpravami, ale změna ceny se nezaznamená. Druhý prohlížeč zobrazuje stejnou hodnotu jako první název nového produktu se starou cenou. Změny provedené v druhém okně prohlížeče byly ztraceny. Změny byly navíc ztraceny dost nenápadně, protože nedošlo k výjimce nebo zprávě oznamující, že došlo k porušení souběžnosti.

Změny v druhém okně prohlížeče byly bezobslužně ztraceny.

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 změny druhého prohlížeče, byla proto, že UPDATE klauzule s WHERE příkazu odfiltrovala všechny záznamy, a proto neměla vliv na žádné řádky. Pojďme se znovu podívat 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 se neshoduje s existujícím názvem produktu (protože byl změněn prvním prohlížečem). Proto příkaz [ProductName] = @original_ProductName 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 jedním a uložením změn. Po uložení změn v jednom prohlížeči klikněte na tlačítko Odstranit pro stejný produkt v druhém. Vzhledem k tomu, že v klauzuli DELETE příkazu WHERE původní hodnoty neodpovídají, odstranění tiše 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 úpravou, ale jejich změny byly ztraceny. Neexistuje ale žádná vizuální zpětná vazba, která by naznačovala, že jejich změny nebyly přijaty. V ideálním případě, pokud dojde ke ztrátě změn uživatele kvůli porušení souběžnosti, upozorníme uživatele a například necháme mřížku v režimu úprav. Pojďme se podívat, jak toho dosáhnout.

Krok 3: Určení, kdy došlo k poruš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 porušení souběžnosti. Chcete-li upozornit uživatele, pojďme přidat ovládací prvek Label Web na začátek stránky, ConcurrencyViolationMessage jejíž Text vlastnost zobrazuje 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 ostatních uživatelů a pak aktualizaci nebo odstranění zopakujte. Nastavte vlastnost ovládacího prvku CssClass Popisek na "Warning", což je třída CSS definovaná v Styles.css a zobrazuje text v červené, kurzívou, tučném a velkém písmu. Nakonec nastavte vlastnosti popisků Visible a EnableViewState na hodnotu False. Tím se skryje popisek s výjimkou těch postbacků, kde jsme explicitně nastavili jeho vlastnost Visible na True.

Přidání ovládacího prvku Popisek na stránku pro zobrazení upozornění

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 gridView s RowUpdated a RowDeleted obslužné rutiny událostí aktivují po provedení požadované aktualizace nebo odstranění ovládacího prvku zdroje dat. Z těchto obslužných rutin událostí můžeme určit, kolik řádků operace ovlivnila. Pokud byly ovlivněny nulové řádky, chceme zobrazit ConcurrencyViolationMessage popisek.

Vytvořte obslužnou rutinu události pro RowUpdated události i RowDeleted události 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í kontrolujeme vlastnost e.AffectedRows a pokud se rovná 0, nastavíme vlastnost Visible u ConcurrencyViolationMessage na True. V obslužné rutině RowUpdated události také dáváme pokyn GridView, aby zůstal v režimu úprav nastavením vlastnosti KeepInEditMode na true. V takovém případě potřebujeme data znovu připojit k mřížce tak, aby se do rozhraní pro úpravy načetla data ostatních uživatelů. Toho se dosahuje voláním Metody GridView s DataBind() .

Jak ukazuje obrázek 9, s těmito dvěma obslužnými rutinami událostí se při výskytu porušení souběžnosti zobrazí velmi znatelná zpráva.

Při porušení souběžnosti se zobrazí zpráva.

Obrázek 9: Při porušení souběžnosti se zobrazí zpráva (kliknutím zobrazíte obrázek v plné velikosti).

Shrnutí

Při vytváření webové aplikace, kde může několik souběžných uživatelů upravovat stejná data, 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 práce související s přidáním rozšířených WHERE klauzulí do automaticky vygenerovaných UPDATE a DELETE příkazů, ale existují některé jemnosti při zpracování NULL sloupců hodnot, jak je popsáno v části Správné zpracování hodnot NULL.

V tomto kurzu se dokončí 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 ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, trenér a spisovatel. Jeho nejnovější kniha je Sams Naučte se ASP.NET 2.0 v 24 hodinách. Může být dosažitelný na mitchell@4GuysFromRolla.comadrese .