Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questa esercitazione vengono esaminati i concetti essenziali del controllo della concorrenza ottimistica e quindi viene illustrato come implementarlo usando il controllo SqlDataSource.
Introduzione
Nell'esercitazione precedente è stato esaminato come aggiungere funzionalità di inserimento, aggiornamento ed eliminazione al controllo SqlDataSource. In breve, per fornire queste funzionalità, abbiamo bisogno di specificare l'istruzione SQL corrispondente nelle proprietà INSERT, UPDATE o DELETE del controllo InsertCommand, UpdateCommand o DeleteCommand, insieme ai parametri appropriati nelle raccolte InsertParameters, UpdateParameters e DeleteParameters. Anche se queste proprietà e raccolte possono essere specificate manualmente, il pulsante Avanzate della procedura guidata Configura origine dati offre una casella di controllo per generare istruzioni INSERT, UPDATE e DELETE che creeranno automaticamente queste istruzioni in base all'istruzione SELECT.
Insieme alla casella di controllo "Genera istruzioni INSERT, UPDATE, e DELETE", la finestra di dialogo delle Opzioni avanzate di generazione SQL include un'opzione "Usa concorrenza ottimistica" (vedere la figura 1). Quando selezionato, le clausole WHERE nelle istruzioni UPDATE e DELETE generate automaticamente vengono modificate per eseguire l'aggiornamento o l'eliminazione solo se i dati del database sottostanti non sono stati modificati da quando l'utente ha caricato per l'ultima volta i dati nella griglia.
Figura 1: È possibile aggiungere il supporto della concorrenza ottimistica dalla finestra di dialogo Opzioni avanzate di generazione SQL
Di nuovo nell'esercitazione Implementazione della concorrenza ottimistica sono stati esaminati i concetti fondamentali del controllo della concorrenza ottimistica e come aggiungerlo a ObjectDataSource. In questo tutorial ripasseremo gli elementi essenziali del controllo della concorrenza ottimistica e poi esploreremo come implementarlo usando SqlDataSource.
Riepilogo della concorrenza ottimistica
Per le applicazioni Web che consentono a più utenti simultanei di modificare o eliminare gli stessi dati, esiste una possibilità che un utente possa sovrascrivere accidentalmente altre modifiche. Nell'esercitazione Implementazione della concorrenza ottimistica ho fornito l'esempio seguente:
Si supponga che due utenti, Jisun e Sam, visitassero entrambe una pagina in un'applicazione che consentiva ai visitatori di aggiornare ed eliminare i prodotti tramite un controllo GridView. Entrambi cliccano sul pulsante Modifica relativo a Chai nello stesso momento. Jisun modifica il nome del prodotto in Chai Tea e fa clic sul pulsante Aggiorna. Il risultato netto è un'istruzione UPDATE inviata al database, che imposta tutti i campi aggiornabili del prodotto (anche se Jisun ha aggiornato un solo campo, ProductName). A questo punto, il database ha i valori Chai Tea, la categoria Beverages, il fornitore Exotic Liquids e così via per questo particolare prodotto. Tuttavia, la schermata GridView in Sam s mostra ancora il nome del prodotto nella riga GridView modificabile come Chai. Qualche secondo dopo il commit delle modifiche apportate a Jisun, Sam aggiorna la categoria a Condimenti e seleziona Aggiorna. Viene inviata al database un'istruzione UPDATE che imposta il nome del prodotto su Chai, imposta CategoryID sull'ID di categoria Condiments corrispondente, e così via. Le modifiche al nome del prodotto apportate da Jisun sono state sovrascritte.
La figura 2 illustra questa interazione.
Figura 2: Quando due utenti aggiornano simultaneamente un record Esiste la possibilità di apportare modifiche a un utente per sovrascrivere l'altro (fare clic per visualizzare l'immagine a dimensione intera)
Per impedire lo svolgimento di questo scenario, è necessario implementare una forma di controllo della concorrenza . La concorrenza ottimistica è il focus di questa esercitazione, che si basa sul presupposto che, sebbene possano verificarsi conflitti di concorrenza di tanto in tanto, nella stragrande maggioranza dei casi tali conflitti non si verificheranno. Pertanto, se si verifica un conflitto, il controllo della concorrenza ottimistica informa semplicemente l'utente che le modifiche non possono essere salvate perché un altro utente ha modificato gli stessi dati.
Annotazioni
Per le applicazioni in cui si presuppone che ci saranno molti conflitti di concorrenza o se tali conflitti non sono tollerabili, è possibile usare invece il controllo di concorrenza pessimistico. Per una discussione più approfondita sul controllo della concorrenza pessimistica, vedere l'esercitazione Implementazione della concorrenza ottimistica .
Il controllo della concorrenza ottimistica funziona verificando che il record da aggiornare o eliminare abbia gli stessi valori di quando è stato avviato il processo di aggiornamento o eliminazione. Ad esempio, quando si fa clic sul pulsante Modifica in un controllo GridView modificabile, i valori del record vengono letti dal database e visualizzati in Caselle di testo e in altri controlli Web. Questi valori originali vengono salvati da GridView. Successivamente, dopo che l'utente apporta le modifiche e fa clic sul pulsante Aggiorna, l'istruzione UPDATE utilizzata deve tenere conto dei valori originali più i nuovi valori e aggiornare il record di database sottostante solo se i valori originali avviati dall'utente sono identici ai valori ancora presenti nel database. La figura 3 illustra questa sequenza di eventi.
Figura 3: Affinché l'aggiornamento o l'eliminazione abbia esito positivo, i valori originali devono essere uguali ai valori correnti del database (fare clic per visualizzare l'immagine a dimensione intera)
Esistono diversi approcci all'implementazione della concorrenza ottimistica (vedere la Logica di aggiornamento con concorrenza ottimistica di Peter A. Bromberg per una breve panoramica delle diverse opzioni). La tecnica usata da SqlDataSource (nonché dai set di dati tipizzati ADO.NET usati nel livello di accesso ai dati) aumenta la WHERE clausola per includere un confronto di tutti i valori originali. L'istruzione seguente UPDATE , ad esempio, aggiorna il nome e il prezzo di un prodotto solo se i valori correnti del database sono uguali ai valori recuperati originariamente durante l'aggiornamento del record in GridView. I @ProductName parametri e @UnitPrice contengono i nuovi valori immessi dall'utente, mentre @original_ProductName e @original_UnitPrice contengono i valori originariamente caricati in GridView quando è stato fatto clic sul pulsante Modifica:
UPDATE Products SET
ProductName = @ProductName,
UnitPrice = @UnitPrice
WHERE
ProductID = @original_ProductID AND
ProductName = @original_ProductName AND
UnitPrice = @original_UnitPrice
Come si vedrà in questa esercitazione, l'abilitazione del controllo della concorrenza ottimistica con SqlDataSource è semplice come selezionare una casella di controllo.
Passaggio 1: Creazione di un SqlDataSource che supporta la concorrenza ottimistica
Per iniziare, aprire la OptimisticConcurrency.aspx pagina dalla SqlDataSource cartella . Trascinare un controllo SqlDataSource dalla casella degli strumenti nella finestra di progettazione, impostare la relativa ID proprietà su ProductsDataSourceWithOptimisticConcurrency. Fare quindi clic sul collegamento Configura origine dati dallo smart tag del controllo. Nella prima schermata della procedura guidata, scegli di lavorare con il NORTHWINDConnectionString e fai clic su Avanti.
Figura 4: Scegliere di lavorare con NORTHWINDConnectionString (fare clic per visualizzare l'immagine a dimensione intera)
Per questo esempio si aggiungerà un controllo GridView che consente agli utenti di modificare la Products tabella. Di conseguenza, nella schermata Configura Istruzione di Selezione, scegliere la tabella Products dall'elenco a discesa e selezionare le colonne ProductID, ProductName, UnitPrice e Discontinued, come illustrato nella Figura 5.
Figura 5: Dalla Products tabella, restituire le colonne ProductID, ProductName, UnitPrice e Discontinued (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver selezionato le colonne, fare clic sul pulsante Avanzate per visualizzare la finestra di dialogo Opzioni avanzate generazione SQL. Selezionare le caselle di controllo Genera istruzioni INSERT, UPDATE, e DELETE, quindi seleziona Usa concorrenza ottimistica e fare clic su OK (fare riferimento alla Figura 1 per uno screenshot). Completare la procedura guidata facendo clic su Avanti, quindi su Fine.
Dopo aver completato la procedura guidata Configura origine dati, prenditi un momento per esaminare le proprietà risultanti DeleteCommand e UpdateCommand e le raccolte DeleteParameters e UpdateParameters. Il modo più semplice per eseguire questa operazione consiste nel fare clic sulla scheda Origine nell'angolo inferiore sinistro per visualizzare la sintassi dichiarativa della pagina. Qui troverai un UpdateCommand valore di:
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
Con sette parametri nella UpdateParameters raccolta:
<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>
Analogamente, la proprietà DeleteCommand e la raccolta DeleteParameters dovrebbe apparire come segue:
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>
Oltre ad aumentare le WHERE clausole delle proprietà UpdateCommand e DeleteCommand (e ad aggiungere i parametri aggiuntivi alle rispettive raccolte di parametri), selezionando l'opzione Usa concorrenza ottimistica vengono modificate due altre proprietà.
- Modifica la
ConflictDetectionproprietà daOverwriteChanges(impostazione predefinita) aCompareAllValues - Modifica la
OldValuesParameterFormatStringproprietà da {0} (impostazione predefinita) a original_{0} .
Quando il controllo Web dati richiama il metodo `Update()` o `Delete()` di SqlDataSource, passa i valori originali. Se la proprietà sqlDataSource s ConflictDetection è impostata su CompareAllValues, questi valori originali vengono aggiunti al comando . La OldValuesParameterFormatString proprietà fornisce il modello di denominazione usato per questi parametri di valore originali. La procedura guidata Configura origine dati utilizza original_{0} e assegna un nome a ciascun parametro originale nelle proprietà UpdateCommand e DeleteCommand, e nelle raccolte UpdateParameters e DeleteParameters di conseguenza.
Annotazioni
Poiché non utilizziamo le funzionalità di inserimento del controllo SqlDataSource, puoi tranquillamente rimuovere la proprietà InsertCommand e la sua raccolta InsertParameters.
Gestione corretta deiNULLvalori
Sfortunatamente, le istruzioni UPDATE e DELETE aumentate generate automaticamente dalla procedura guidata Configura origine dati quando si usa la concorrenza ottimistica non funzionano con i record che contengono NULL valori. Per vedere perché, prendere in considerazione 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
La UnitPrice colonna nella Products tabella può avere NULL valori. Se un determinato record ha un NULL valore per UnitPrice, la parte WHERE della [UnitPrice] = @original_UnitPrice clausola restituirà sempre False perché NULL = NULL restituisce sempre False. Pertanto, i record che contengono NULL valori non possono essere modificati o eliminati, perché le UPDATE clausole e DELETEWHERE non restituiscono righe da aggiornare o eliminare.
Annotazioni
Questo bug è stato segnalato per la prima volta a Microsoft nel mese di giugno 2004 in SqlDataSource genera istruzioni SQL non corrette e viene segnalato come corretto nella versione successiva di ASP.NET.
Per risolvere questo problema, è necessario aggiornare manualmente le WHERE clausole in entrambe le UpdateCommand proprietà e DeleteCommand per tutte le colonne che possono avere NULL valori. In generale, passare [ColumnName] = @original_ColumnName a:
(
([ColumnName] IS NULL AND @original_ColumnName IS NULL)
OR
([ColumnName] = @original_ColumnName)
)
Questa modifica può essere apportata direttamente tramite il markup dichiarativo, tramite le opzioni UpdateQuery o DeleteQuery dalla finestra Proprietà oppure tramite le schede UPDATE e DELETE nell'opzione Specificare un'istruzione SQL personalizzata o una stored procedure nella procedura guidata Configura origine dati. Anche in questo caso, questa modifica deve essere apportata per ogni colonna nella UpdateCommand e nella clausola DeleteCommandWHERE che può contenere NULL valori.
Applicando questo al nostro esempio si ottengono i seguenti valori modificati UpdateCommand e 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
Passaggio 2: Aggiunta di un controllo GridView con opzioni di modifica ed eliminazione
Con SqlDataSource configurato per supportare la concorrenza ottimistica, tutto ciò che rimane consiste nell'aggiungere un controllo Web dati alla pagina che utilizza questo controllo di concorrenza. Per questa esercitazione, è possibile aggiungere un controllo GridView che fornisce funzionalità di modifica ed eliminazione. A tale scopo, trascinare un controllo GridView dalla casella degli strumenti nella finestra di progettazione e impostarne il valore ID su Products. Dallo smart tag del GridView, associarlo al ProductsDataSourceWithOptimisticConcurrency controllo SqlDataSource aggiunto al passaggio 1. Infine, selezionare le opzioni Abilita modifica e Abilita eliminazione dallo smart tag.
Figura 6: Associare GridView a SqlDataSource e abilitare la modifica e l'eliminazione (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver aggiunto il GridView, configurarne l'aspetto rimuovendo il BoundField ProductID, modificando la proprietà del BoundField ProductName in Prodotto e aggiornando il BoundField HeaderText in modo che la sua proprietà sia semplicemente Prezzo. Idealmente, si migliora l'interfaccia di modifica per includere un RequiredFieldValidator per il ProductName valore e un CompareValidator per il UnitPrice valore (per assicurarsi che si tratti di un valore numerico formattato correttamente). Per un'analisi più approfondita sulla personalizzazione dell'interfaccia di modifica di GridView, fare riferimento all'esercitazione Personalizzazione dell'interfaccia di modifica dei dati.
Annotazioni
Lo stato di visualizzazione di GridView deve essere abilitato perché i valori originali passati da GridView a SqlDataSource vengono archiviati nello stato di visualizzazione.
Dopo aver apportato queste modifiche a GridView, il markup dichiarativo GridView e SqlDataSource dovrebbe essere simile al seguente:
<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>
Per visualizzare il controllo della concorrenza ottimistica in azione, aprire due finestre del browser e caricare la pagina OptimisticConcurrency.aspx in entrambe. Fare clic sui pulsanti Modifica per il primo prodotto in entrambi i browser. In un browser modificare il nome del prodotto e fare clic su Aggiorna. Il browser eseguirà il postback e GridView tornerà alla modalità di pre-modifica, mostrando il nuovo nome del prodotto per il record appena modificato.
Nella seconda finestra del browser modificare il prezzo (ma lasciare il nome del prodotto come valore originale) e fare clic su Aggiorna. Durante il postback, la griglia torna alla modalità di modifica precedente, ma la modifica del prezzo non viene registrata. Il secondo browser mostra lo stesso valore del primo: il nome del nuovo prodotto con il prezzo precedente. Le modifiche apportate nella seconda finestra del browser sono andate perse. Inoltre, le modifiche sono andate perdute in modo piuttosto silenzioso, perché non vi erano eccezioni o messaggi che indicano che si è appena verificata una violazione della concorrenza.
Figura 7: Le modifiche nella seconda finestra del browser sono state perse automaticamente (fare clic per visualizzare l'immagine a dimensione intera)
Il motivo per cui non è stato eseguito il commit delle modifiche apportate al secondo browser è dovuto al fatto che la clausola dell'istruzione UPDATEWHERE ha filtrato tutti i record e pertanto non ha avuto alcun effetto sulle righe. Esaminiamo di nuovo l'istruzione 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
Quando la seconda finestra del browser aggiorna il record, il nome del prodotto originale specificato nella WHERE clausola non corrisponde al nome del prodotto esistente (poiché è stato modificato dal primo browser). Pertanto, l'istruzione [ProductName] = @original_ProductName restituisce False e UPDATE non influisce su alcun record.
Annotazioni
La cancellazione funziona nello stesso modo. Con due finestre del browser aperte, iniziare modificando un determinato prodotto con uno e quindi salvandone le modifiche. Dopo aver salvato le modifiche in un browser, fare clic sul pulsante Elimina per lo stesso prodotto nell'altro. Poiché i valori originali non corrispondono nella clausola DELETE dell'istruzione WHERE, l'eliminazione ha esito negativo in modo invisibile all'utente.
Dal punto di vista dell'utente finale nella seconda finestra del browser, dopo aver fatto clic sul pulsante Aggiorna, la griglia torna alla modalità di pre-modifica, ma le modifiche sono andate perse. Tuttavia, non c'è alcun feedback visivo che le modifiche non sono state ancorate. Idealmente, se le modifiche apportate a un utente vengono perse in caso di violazione della concorrenza, è necessario notificarle e, forse, mantenere la griglia in modalità di modifica. Vediamo come eseguire questa operazione.
Passaggio 3: Determinare quando si è verificata una violazione di concorrenza
Poiché una violazione di concorrenza rifiuta le modifiche apportate, sarebbe opportuno avvisare l'utente quando si è verificata una violazione della concorrenza. Per avvisare l'utente, è possibile aggiungere un controllo Web Label nella parte superiore della pagina denominata ConcurrencyViolationMessage la cui Text proprietà visualizza il messaggio seguente: Si è tentato di aggiornare o eliminare un record che è stato aggiornato contemporaneamente da un altro utente. Per favore, esamina le modifiche dell'altro utente e quindi aggiorna nuovamente o elimina, se necessario. Impostare la proprietà S CssClass del controllo Label su Warning, ovvero una classe CSS definita in Styles.css che visualizza il testo in un tipo di carattere rosso, corsivo, grassetto e grande. Infine, impostare le proprietà dell'etichetta Visible e EnableViewState su false. In questo modo, l'etichetta verrà nascosta ad eccezione solo dei postback in cui la proprietà viene Visible impostata in modo esplicito su true.
Figura 8: Aggiungere un controllo Etichetta alla pagina per visualizzare l'avviso (fare clic per visualizzare l'immagine a dimensione intera)
Quando si esegue un aggiornamento o un'eliminazione, i gestori eventi RowUpdated e RowDeleted GridView vengono attivati dopo che il controllo origine dati ha eseguito l'aggiornamento o l'eliminazione richiesti. È possibile determinare il numero di righe interessate dall'operazione attraverso questi gestori di eventi. Se sono state interessate zero righe, si vuole visualizzare l'etichetta ConcurrencyViolationMessage .
Creare un gestore eventi per gli RowUpdated eventi e RowDeleted e aggiungere il codice seguente:
protected void Products_RowUpdated(object sender, GridViewUpdatedEventArgs e)
{
if (e.AffectedRows == 0)
{
ConcurrencyViolationMessage.Visible = true;
e.KeepInEditMode = true;
// Rebind the data to the GridView to show the latest changes
Products.DataBind();
}
}
protected void Products_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
if (e.AffectedRows == 0)
ConcurrencyViolationMessage.Visible = true;
}
In entrambi i gestori eventi si controlla la e.AffectedRows proprietà e, se è uguale a 0, impostare la ConcurrencyViolationMessage proprietà Label s Visible su true.
RowUpdated Nel gestore eventi viene inoltre indicato a GridView di rimanere in modalità di modifica impostando la KeepInEditMode proprietà su true. In questo modo, è necessario riassociare i dati alla griglia in modo che gli altri dati dell'utente vengano caricati nell'interfaccia di modifica. A tale scopo, chiamare il metodo gridView s DataBind() .
Come illustrato nella figura 9, con questi due gestori eventi, viene visualizzato un messaggio molto evidente ogni volta che si verifica una violazione della concorrenza.
Figura 9: Un messaggio viene visualizzato in faccia a una violazione di concorrenza (fare clic per visualizzare l'immagine a dimensione intera)
Riassunto
Quando si crea un'applicazione Web in cui più utenti simultanei possono modificare gli stessi dati, è importante considerare le opzioni di controllo della concorrenza. Per impostazione predefinita, i controlli Web dati ASP.NET e i controlli origine dati non usano alcun controllo di concorrenza. Come illustrato in questa esercitazione, l'implementazione del controllo della concorrenza ottimistica con SqlDataSource è relativamente rapida e semplice. SqlDataSource gestisce la maggior parte del lavoro necessario per l'aggiunta di clausole aumentate WHERE alle istruzioni UPDATE e DELETE generate automaticamente, ma ci sono alcune sottigliezze nella gestione delle colonne di valore NULL, come discusso nella sezione Gestione corretta dei valori NULL.
Questa esercitazione conclude l'esame di SqlDataSource. Le esercitazioni rimanenti torneranno a lavorare con i dati usando ObjectDataSource e l'architettura a livelli.
Buon programmatori!
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto a mitchell@4GuysFromRolla.com.