Implementowanie optymistycznej współbieżności przy użyciu kontrolki SqlDataSource (VB)
W tym samouczku zapoznamy się z podstawowymi elementami optymistycznej kontroli współbieżności, a następnie dowiesz się, jak zaimplementować ją przy użyciu kontrolki SqlDataSource.
Wprowadzenie
W poprzednim samouczku sprawdziliśmy, jak dodać funkcje wstawiania, aktualizowania i usuwania do kontrolki SqlDataSource. Krótko mówiąc, aby zapewnić te funkcje, musieliśmy określić odpowiednią INSERT
instrukcję , UPDATE
lub DELETE
SQL w kontrolce s InsertCommand
, UpdateCommand
lub DeleteCommand
właściwości wraz z odpowiednimi parametrami w InsertParameters
UpdateParameters
kolekcjach , i DeleteParameters
. Chociaż te właściwości i kolekcje można określić ręcznie, przycisk Zaawansowane Kreatora konfigurowania źródła danych oferuje pole wyboru Generuj INSERT
instrukcje , UPDATE
i DELETE
, które automatycznie utworzy te instrukcje na SELECT
podstawie instrukcji .
Wraz z polem wyboru Generuj INSERT
instrukcje , UPDATE
i DELETE
okno dialogowe Zaawansowane opcje generowania SQL zawiera opcję Użyj optymistycznej współbieżności (zobacz Rysunek 1). Po sprawdzeniu klauzule w automatycznie wygenerowanych UPDATE
instrukcjach i DELETE
są modyfikowane w celu przeprowadzenia aktualizacji lub usunięcia tylko wtedy, WHERE
gdy bazowe dane bazy danych nie zostały zmodyfikowane od czasu ostatniego załadowania danych przez użytkownika do siatki.
Rysunek 1. Możesz dodać optymistyczną obsługę współbieżności z okna dialogowego Zaawansowane opcje generowania SQL
W samouczku Implementowanie optymistycznej współbieżności przeanalizowaliśmy podstawy optymistycznej kontroli współbieżności i sposób dodawania jej do obiektu ObjectDataSource. W tym samouczku omówimy podstawy optymistycznej kontrolki współbieżności, a następnie dowiesz się, jak zaimplementować ją przy użyciu usługi SqlDataSource.
Podsumowanie optymistycznej współbieżności
W przypadku aplikacji internetowych, które umożliwiają wielu, równoczesnym użytkownikom edytowanie lub usuwanie tych samych danych, istnieje możliwość, że jeden użytkownik może przypadkowo zastąpić inne zmiany. W samouczku Implementowanie optymistycznej współbieżności podano następujący przykład:
Załóżmy, że dwóch użytkowników, Jisun i Sam, odwiedzało stronę w aplikacji, która zezwalała odwiedzającym na aktualizowanie i usuwanie produktów za pomocą kontrolki GridView. Obaj kliknij przycisk Edytuj dla chai mniej więcej w tym samym czasie. Jisun zmienia nazwę produktu na Chai Tea i klika przycisk Aktualizuj. Wynikiem net jest UPDATE
instrukcja, która jest wysyłana do bazy danych, która ustawia wszystkie pola z możliwością aktualizacji produktu (mimo że Jisun zaktualizował tylko jedno pole, ProductName
). W tym momencie baza danych ma wartości Chai Tea, kategorię Napoje, dostawca Egzotyczne płyny itd. dla tego konkretnego produktu. Jednak na ekranie GridView na ekranie Sam nadal wyświetlana jest nazwa produktu w edytowalnym wierszu GridView jako Chai. Kilka sekund po zatwierdzeniu zmian programu Jisun sam aktualizuje kategorię na Condiments i klika pozycję Aktualizuj. UPDATE
Spowoduje to wysłanie instrukcji do bazy danych, która ustawia nazwę produktu na Chai, CategoryID
na odpowiadający identyfikator kategorii Condiments itd. Zmiany w nazwie produktu jisun zostały zastąpione.
Rysunek 2 ilustruje tę interakcję.
Rysunek 2. Gdy dwóch użytkowników jednocześnie zaktualizuje rekord, istnieje możliwość zmiany jednego użytkownika w celu zastąpienia drugiego (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Aby zapobiec rozwojowi tego scenariusza, należy zaimplementować formę kontrolki współbieżności . Optymistyczna współbieżność skupiona na tym samouczku działa na założeniu, że chociaż konflikty współbieżności mogą występować co chwilę, zdecydowana większość czasu takich konfliktów nie wystąpi. W związku z tym, jeśli wystąpi konflikt, optymistyczna kontrola współbieżności po prostu informuje użytkownika, że ich zmiany nie można zapisać, ponieważ inny użytkownik zmodyfikował te same dane.
Uwaga
W przypadku aplikacji, w których zakłada się, że wystąpi wiele konfliktów współbieżności lub jeśli takie konflikty nie są tolerowane, można zamiast tego użyć pesymistycznej kontrolki współbieżności. Zapoznaj się z samouczkiem Implementowanie optymistycznej współbieżności , aby uzyskać bardziej szczegółową dyskusję na temat pesymistycznej kontroli współbieżności.
Optymistyczna kontrola współbieżności działa, upewniając się, że rekord aktualizowany lub usuwany ma te same wartości co podczas uruchamiania procesu aktualizowania lub usuwania. Na przykład po kliknięciu przycisku Edytuj w edytowalnym elemecie GridView wartości rekordów są odczytywane z bazy danych i wyświetlane w polach TextBoxes i innych kontrolkach sieci Web. Te oryginalne wartości są zapisywane przez element GridView. Później, gdy użytkownik wprowadza zmiany i klika przycisk Aktualizuj, UPDATE
użyta instrukcja musi uwzględniać oryginalne wartości oraz nowe wartości i aktualizować tylko bazowy rekord bazy danych, jeśli oryginalne wartości, które użytkownik zaczął edytować, są identyczne z wartościami nadal w bazie danych. Rysunek 3 przedstawia tę sekwencję zdarzeń.
Rysunek 3. Aby aktualizacja lub usunięcie powiodło się, oryginalne wartości muszą być równe bieżącym wartościom bazy danych (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Istnieją różne podejścia do implementowania optymistycznej współbieżności (zobacz Optymistyczna logika aktualizacji współbieżnościPetera A. Bromberga, aby zapoznać się z kilkoma opcjami). Technika używana przez usługę SqlDataSource (a także przez zestawy danych typu ADO.NET używanych w warstwie dostępu do danych) rozszerza WHERE
klauzulę, aby uwzględnić porównanie wszystkich oryginalnych wartości. Poniższa UPDATE
instrukcja aktualizuje na przykład nazwę i cenę produktu tylko wtedy, gdy bieżące wartości bazy danych są równe wartościom, które zostały pierwotnie pobrane podczas aktualizowania rekordu w elemencie GridView. Parametry @ProductName
i @UnitPrice
zawierają nowe wartości wprowadzone przez użytkownika, natomiast @original_ProductName
i @original_UnitPrice
zawierają wartości, które zostały pierwotnie załadowane do kontrolki GridView po kliknięciu przycisku Edytuj:
UPDATE Products SET
ProductName = @ProductName,
UnitPrice = @UnitPrice
WHERE
ProductID = @original_ProductID AND
ProductName = @original_ProductName AND
UnitPrice = @original_UnitPrice
Jak zobaczymy w tym samouczku, włączenie optymistycznej kontrolki współbieżności z usługą SqlDataSource jest tak proste, jak zaznaczenie pola wyboru.
Krok 1. Tworzenie bazy danych SqlDataSource obsługującej optymistyczną współbieżność
Zacznij od otwarcia OptimisticConcurrency.aspx
strony z SqlDataSource
folderu. Przeciągnij kontrolkę SqlDataSource z przybornika na Projektant, a następnie ustaw jej ID
właściwość na ProductsDataSourceWithOptimisticConcurrency
. Następnie kliknij link Konfiguruj źródło danych z tagu inteligentnego kontrolki. Na pierwszym ekranie kreatora wybierz pracę z elementem NORTHWINDConnectionString
i kliknij przycisk Dalej.
Rysunek 4. Wybierz opcję Pracy z (NORTHWINDConnectionString
kliknij, aby wyświetlić obraz pełnowymiarowy)
W tym przykładzie dodamy element GridView, który umożliwia użytkownikom edytowanie Products
tabeli. W związku z tym na ekranie Konfigurowanie instrukcji Select wybierz Products
tabelę z listy rozwijanej i wybierz ProductID
kolumny , , UnitPrice
ProductName
iDiscontinued
, jak pokazano na rysunku 5.
Rysunek 5. Z Products
tabeli zwróć ProductID
kolumny , ProductName
, UnitPrice
i Discontinued
(kliknij, aby wyświetlić obraz pełnowymiarowy)
Po wybraniu kolumn kliknij przycisk Zaawansowane, aby wyświetlić okno dialogowe Zaawansowane opcje generacji SQL. Zaznacz pola wyboru Generuj INSERT
instrukcje , UPDATE
i DELETE
Użyj optymistycznej współbieżności, a następnie kliknij przycisk OK (zapoznaj się z rysunkiem 1 na zrzucie ekranu). Ukończ pracę kreatora, klikając przycisk Dalej, a następnie zakończ.
Po ukończeniu pracy Kreatora konfigurowania źródła danych poświęć chwilę, aby sprawdzić wynikowe DeleteCommand
właściwości i UpdateCommand
kolekcje i DeleteParameters
.UpdateParameters
Najprostszym sposobem, aby to zrobić, jest kliknięcie karty Źródło w lewym dolnym rogu, aby wyświetlić składnię deklaracyjną strony. W tym miejscu znajdziesz UpdateCommand
wartość:
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
Z siedmiu parametrów w kolekcji 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>
Podobnie właściwość i DeleteParameters
kolekcja powinny wyglądać następującoDeleteCommand
:
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>
Oprócz rozszerzania WHERE
klauzul UpdateCommand
właściwości i DeleteCommand
(i dodawania dodatkowych parametrów do odpowiednich kolekcji parametrów), wybranie opcji Użyj optymistycznej współbieżności dostosowuje dwie inne właściwości:
ConflictDetection
Zmienia właściwość zOverwriteChanges
(wartość domyślna) naCompareAllValues
OldValuesParameterFormatString
Zmienia właściwość z {0} (wartość domyślna) na original_{0} .
Gdy kontrolka internetowa danych wywołuje metodę SqlDataSource lub Update()
Delete()
, przekazuje oryginalne wartości. Jeśli właściwość SqlDataSource jest ustawiona ConflictDetection
na CompareAllValues
, te oryginalne wartości zostaną dodane do polecenia . Właściwość OldValuesParameterFormatString
udostępnia wzorzec nazewnictwa używany dla tych oryginalnych parametrów wartości. Kreator Konfigurowania źródła danych używa original_{0} i nazwy każdego oryginalnego parametru we UpdateCommand
właściwościach i DeleteCommand
kolekcjach oraz UpdateParameters
odpowiednio DeleteParameters
.
Uwaga
Ponieważ nie używamy możliwości wstawiania kontrolki SqlDataSource, możesz usunąć InsertCommand
właściwość i jej InsertParameters
kolekcję.
Poprawne obsługaNULL
wartości
Niestety rozszerzone UPDATE
instrukcje i DELETE
automatycznie generowane przez Kreatora konfigurowania źródła danych w przypadku korzystania z optymistycznej współbieżności nie działają z rekordami zawierającymi NULL
wartości. Aby zobaczyć, dlaczego warto rozważyć nasze źródło danych 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
Kolumna UnitPrice
Products
w tabeli może zawierać NULL
wartości. Jeśli określony rekord ma NULL
wartość , UnitPrice
WHERE
część [UnitPrice] = @original_UnitPrice
klauzuli zawsze będzie oceniać wartość False, ponieważ NULL = NULL
zawsze zwraca wartość False. W związku z tym rekordy zawierające NULL
wartości nie mogą być edytowane ani usuwane, ponieważ UPDATE
klauzule and DELETE
WHERE
nie będą zwracać żadnych wierszy do aktualizacji ani usunięcia.
Uwaga
Ta usterka została po raz pierwszy zgłoszona firmie Microsoft w czerwcu 2004 r. w usłudze SqlDataSource generuje nieprawidłowe instrukcje SQL i podobno ma zostać naprawiona w następnej wersji ASP.NET.
Aby rozwiązać ten problem, musimy ręcznie zaktualizować WHERE
klauzule zarówno we właściwościach, jak UpdateCommand
i DeleteCommand
dla wszystkich kolumn, które mogą mieć NULL
wartości. Ogólnie rzecz biorąc, zmień na [ColumnName] = @original_ColumnName
:
(
([ColumnName] IS NULL AND @original_ColumnName IS NULL)
OR
([ColumnName] = @original_ColumnName)
)
Tę modyfikację można wprowadzić bezpośrednio za pomocą znaczników deklaratywnych, za pośrednictwem opcji UpdateQuery lub DeleteQuery z okno Właściwości lub za pomocą kart UPDATE i DELETE w opcji Określ niestandardową instrukcję SQL lub procedurę składowaną w kreatorze Konfigurowanie źródła danych. Ponownie należy wprowadzić tę modyfikację dla każdej kolumny w klauzuli UpdateCommand
i WHERE
DeleteCommand
, która może zawierać NULL
wartości.
Zastosowanie tej funkcji do naszego przykładu powoduje zmodyfikowanie następujących UpdateCommand
wartości i 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. Dodawanie kontrolki GridView z opcjami edycji i usuwania
Po skonfigurowaniu usługi SqlDataSource do obsługi optymistycznej współbieżności pozostaje dodanie kontrolki sieci Web danych do strony korzystającej z tej kontrolki współbieżności. Na potrzeby tego samouczka dodajmy element GridView, który zapewnia zarówno funkcje edytowania, jak i usuwania. Aby to osiągnąć, przeciągnij element GridView z przybornika na Projektant i ustaw go ID
na Products
wartość . Z tagu inteligentnego GridView powiąż go z kontrolką ProductsDataSourceWithOptimisticConcurrency
SqlDataSource dodaną w kroku 1. Na koniec zaznacz opcje Włącz edytowanie i Włącz usuwanie z tagu inteligentnego.
Rysunek 6. Powiązanie widoku GridView z usługą SqlDataSource i włączanie edycji i usuwania (kliknij, aby wyświetlić obraz pełnowymiarowy)
Po dodaniu obiektu GridView skonfiguruj jego wygląd, usuwając ProductID
właściwość BoundField, zmieniając ProductName
właściwość BoundField HeaderText
na Product i aktualizując UnitPrice
pole BoundField tak, aby jej HeaderText
właściwość to po prostu Price. W idealnym przypadku rozszerzyliśmy interfejs edycji tak, aby zawierał element RequiredFieldValidator dla ProductName
wartości i parametr CompareValidator dla UnitPrice
wartości (aby upewnić się, że jest to prawidłowo sformatowana wartość liczbowa). Zapoznaj się z samouczkiem Dostosowywanie interfejsu modyfikacji danych , aby uzyskać bardziej szczegółowe informacje na temat dostosowywania interfejsu edycji kontrolki GridView.
Uwaga
Stan widoku kontrolki GridView musi być włączony, ponieważ oryginalne wartości przekazane z obiektu GridView do elementu SqlDataSource są przechowywane w stanie widoku.
Po wprowadzeniu tych modyfikacji w elementy GridView znaczniki deklaratywne GridView i SqlDataSource powinny wyglądać podobnie do następujących:
<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>
Aby zobaczyć optymistyczną kontrolę współbieżności w działaniu, otwórz dwa okna przeglądarki i załaduj OptimisticConcurrency.aspx
stronę w obu. Kliknij przyciski Edytuj dla pierwszego produktu w obu przeglądarkach. W jednej przeglądarce zmień nazwę produktu i kliknij przycisk Aktualizuj. Przeglądarka zostanie zwrócona, a kontrolka GridView powróci do trybu przed edycją, pokazując nową nazwę produktu dla rekordu, który został właśnie edytowany.
W drugim oknie przeglądarki zmień cenę (ale pozostaw nazwę produktu jako oryginalną wartość) i kliknij przycisk Aktualizuj. Po powrocie siatka powraca do trybu przed edycją, ale zmiana ceny nie jest rejestrowana. Druga przeglądarka wyświetla taką samą wartość jak pierwsza nowa nazwa produktu ze starą ceną. Zmiany wprowadzone w drugim oknie przeglądarki zostały utracone. Ponadto zmiany zostały utracone dość cicho, ponieważ nie było wyjątku ani komunikatu wskazującego, że właśnie doszło do naruszenia współbieżności.
Rysunek 7. Zmiany w drugim oknie przeglądarki zostały utracone w trybie dyskretnym (kliknij, aby wyświetlić obraz pełnowymiarowy)
Powodem, dla którego zmiany drugiej przeglądarki nie zostały zatwierdzone, było to, że UPDATE
klauzula s WHERE
instrukcji odfiltrowała wszystkie rekordy i w związku z tym nie miała wpływu na żadne wiersze. Ponownie przyjrzyjmy się instrukcji UPDATE
:
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
Gdy drugie okno przeglądarki aktualizuje rekord, oryginalna nazwa produktu określona w WHERE
klauzuli nie jest zgodna z istniejącą nazwą produktu (ponieważ została zmieniona przez pierwszą przeglądarkę). W związku z tym instrukcja [ProductName] = @original_ProductName
zwraca wartość False i UPDATE
nie ma wpływu na żadne rekordy.
Uwaga
Usuwanie działa w taki sam sposób. Po otwarciu dwóch okien przeglądarki rozpocznij od edytowania danego produktu przy użyciu jednego, a następnie zapisania zmian. Po zapisaniu zmian w jednej przeglądarce kliknij przycisk Usuń dla tego samego produktu w drugiej. Ponieważ oryginalne wartości nie pasują do klauzuli s WHERE
instrukcjiDELETE
, usuwanie w trybie dyskretnym kończy się niepowodzeniem.
Z perspektywy użytkownika końcowego w drugim oknie przeglądarki po kliknięciu przycisku Aktualizuj siatka powróci do trybu przed edycją, ale ich zmiany zostały utracone. Nie ma jednak żadnych wizualnych opinii, że ich zmiany nie utkną. W idealnym przypadku, jeśli zmiany użytkownika zostaną utracone z naruszeniem współbieżności, powiadomimy ich i, być może, zachowaj siatkę w trybie edycji. Przyjrzyjmy się temu, jak to osiągnąć.
Krok 3. Określanie, kiedy wystąpiło naruszenie współbieżności
Ponieważ naruszenie współbieżności odrzuca wprowadzone zmiany, warto powiadomić użytkownika o wystąpieniu naruszenia współbieżności. Aby zaalarmować użytkownika, dodajmy kontrolkę Sieć Web etykiet w górnej części strony o nazwie ConcurrencyViolationMessage
, której Text
właściwość wyświetla następujący komunikat: Podjęto próbę zaktualizowania lub usunięcia rekordu, który został jednocześnie zaktualizowany przez innego użytkownika. Przejrzyj zmiany innego użytkownika, a następnie ponów aktualizację lub usuń. Ustaw właściwość kontrolki Etykieta CssClass
na Ostrzeżenie, która jest klasą CSS zdefiniowaną w Styles.css
języku , która wyświetla tekst na czerwono, kursywę, pogrubienie i dużą czcionkę. Na koniec ustaw właściwość Etykieta Visible
i EnableViewState
na False
wartość . Spowoduje to ukrycie etykiety z wyjątkiem tylko tych ogłaszania zwrotnego, w których jawnie ustawimy jej Visible
właściwość na True
wartość .
Rysunek 8. Dodawanie kontrolki etykiety do strony w celu wyświetlenia ostrzeżenia (kliknij, aby wyświetlić obraz pełnowymiarowy)
Podczas przeprowadzania aktualizacji lub usuwania programy obsługi zdarzeń GridView RowUpdated
są RowDeleted
uruchamiane po wykonaniu żądanej aktualizacji lub usunięcia kontroli źródła danych. Możemy określić, ile wierszy wpłynęło na operację z tych procedur obsługi zdarzeń. Jeśli nie ma to wpływu na zero wierszy, chcemy wyświetlić etykietę ConcurrencyViolationMessage
.
Utwórz procedurę obsługi zdarzeń dla zdarzeń RowUpdated
i i RowDeleted
i dodaj następujący kod:
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
W obu programach obsługi zdarzeń sprawdzamy e.AffectedRows
właściwość , a jeśli jest równa 0, ustaw ConcurrencyViolationMessage
właściwość Etykieta Visible
na True
wartość . W procedurze obsługi zdarzeń RowUpdated
instruujemy również obiekt GridView, aby pozostał w trybie edycji, ustawiając KeepInEditMode
właściwość na true. W ten sposób musimy ponownie połączyć dane z siatką, aby inne dane użytkownika zostały załadowane do interfejsu edycji. Jest to realizowane przez wywołanie metody GridView.DataBind()
Jak pokazano na rysunku 9, przy użyciu tych dwóch procedur obsługi zdarzeń jest wyświetlany bardzo zauważalny komunikat przy każdym wystąpieniu naruszenia współbieżności.
Rysunek 9. Komunikat jest wyświetlany na twarzy naruszenia współbieżności (kliknij, aby wyświetlić obraz w pełnym rozmiarze)
Podsumowanie
Podczas tworzenia aplikacji internetowej, w której wielu współbieżnych użytkowników może edytować te same dane, należy wziąć pod uwagę opcje kontroli współbieżności. Domyślnie kontrolki sieci Web i źródła danych ASP.NET nie korzystają z żadnej kontrolki współbieżności. Jak pokazano w tym samouczku, implementacja optymistycznej kontroli współbieżności za pomocą usługi SqlDataSource jest stosunkowo szybka i łatwa. Element SqlDataSource obsługuje większość prac związanych z dodawaniem klauzul rozszerzonych WHERE
do automatycznie wygenerowanych UPDATE
instrukcji i DELETE
, ale istnieje kilka subtelności obsługi NULL
kolumn wartości, jak opisano w sekcji Poprawnie obsługiwane NULL
wartości.
Ten samouczek kończy badanie elementu SqlDataSource. Pozostałe samouczki powrócą do pracy z danymi przy użyciu obiektu ObjectDataSource i architektury warstwowej.
Szczęśliwe programowanie!
Informacje o autorze
Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.