Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här självstudien går vi igenom grunderna för optimistisk samtidighetskontroll och utforskar sedan hur du implementerar den med hjälp av SqlDataSource-kontrollen.
Inledning
I föregående självstudie undersökte vi hur du lägger till infognings-, uppdaterings- och borttagningsfunktioner i SqlDataSource-kontrollen. För att kortfattat tillhandahålla dessa funktioner behövde vi ange motsvarande INSERT, UPDATE eller DELETE SQL-instruktion i egenskaperna för kontrollens InsertCommand, UpdateCommand eller DeleteCommand, tillsammans med lämpliga parametrar i samlingarna InsertParameters, UpdateParameters och DeleteParameters. Även om dessa egenskaper och samlingar kan anges manuellt, erbjuder den avancerade knappen i guiden Konfigurera datakälla kryssrutan Generera INSERT, UPDATE och DELETE instruktioner som automatiskt skapar dessa instruktioner baserat på SELECT-instruktionen.
Tillsammans med kryssrutan Generera INSERT, UPDATEoch DELETE -instruktioner innehåller dialogrutan Avancerade ALTERNATIV för SQL-generering alternativet Använd optimistisk samtidighet (se bild 1). När WHERE har markerats ändras satserna i autogenererade UPDATE- och DELETE-uttrycken för att endast utföra uppdateringen eller borttagningen om databasinformationen inte har ändrats sedan användaren senast laddade data i rutnätet.
Bild 1: Du kan lägga till stöd för optimistisk samtidighet från dialogrutan Avancerade ALTERNATIV för SQL-generering
I självstudien Implementering av optimistisk samtidighet undersökte vi grunderna i optimistisk samtidighetskontroll och hur du lägger till den i ObjectDataSource. I den här handledningen gör vi en översikt över grunderna i optimistisk samtidighetsstyrning och utforskar sedan hur vi implementerar den med hjälp av SqlDataSource.
En sammanfattning av optimistisk konkurrens
För webbapplikationer som ger möjlighet för flera användare att samtidigt redigera eller ta bort samma data, finns det en möjlighet att en användare av misstag skriver över en annans ändringar. I tutorialen Implementering av optimistisk konkurrens gav jag följande exempel:
Anta att två användare, Jisun och Sam, båda besökte en sida i ett program som gjorde det möjligt för besökare att uppdatera och ta bort produkter via en GridView-kontroll. Båda klickar på knappen Redigera för Chai ungefär samtidigt. Jisun ändrar produktnamnet till Chai Tea och klickar på knappen Uppdatera. Nettoresultatet är en UPDATE -instruktion som skickas till databasen, som anger alla produkters uppdateringsbara fält (även om Jisun bara uppdaterade ett fält, ProductName). Vid den här tidpunkten har databasen värdena Chai Tea, kategorin Drycker, leverantören Exotic Liquids och så vidare för just den här produkten. GridView på Sams skärm visar dock fortfarande produktnamnet på den redigerbara GridView-raden som Chai. Några sekunder efter att Jisuns ändringar har checkats in uppdaterar Sam kategorin till Condiments och klickar på Uppdatera. Detta resulterar i en UPDATE instruktion som skickas till databasen som anger produktnamnet till Chai, CategoryID motsvarande kategori-ID för condiments och så vidare. Jisuns ändringar av produktnamnet har skrivits över.
Bild 2 illustrerar den här interaktionen.
Bild 2: När två användare samtidigt uppdaterar en post finns det potential för en användares ändringar att skriva över de andra (klicka om du vill visa en bild i full storlek)
För att förhindra att det här scenariot utvecklas måste en form av samtidighetskontroll implementeras. Optimistisk samtidighet i denna handledning fokuserar på antagandet att även om samtidighetskonflikter kan uppstå då och då, kommer sådana konflikter sällan att inträffa. Om en konflikt uppstår informerar därför optimistisk samtidighetskontroll användaren om att deras ändringar inte kan sparas eftersom en annan användare har ändrat samma data.
Anmärkning
För program där det antas att det kommer att finnas många samtidighetskonflikter eller om sådana konflikter inte kan tolereras kan pessimistisk samtidighetskontroll användas i stället. Gå tillbaka till självstudien Implementera optimistisk samtidighet för en mer ingående diskussion om hur pessimistisk samtidighetskontroll fungerar.
Optimistisk samtidighetskontroll fungerar genom att säkerställa att posten som uppdateras eller tas bort har samma värden som när uppdaterings- eller borttagningsprocessen startade. När du till exempel klickar på knappen Redigera i en redigerbar GridView läses postens värden från databasen och visas i Textrutor och andra webbkontroller. Dessa ursprungliga värden sparas av GridView. Senare, när användaren har gjort sina ändringar och klickar på knappen Uppdatera, måste den UPDATE instruktion som används ta hänsyn till de ursprungliga värdena plus de nya värdena och endast uppdatera den underliggande databasposten om de ursprungliga värdena som användaren började redigera är identiska med värdena som fortfarande finns i databasen. Bild 3 visar den här sekvensen med händelser.
Bild 3: För att uppdateringen eller borttagningen ska lyckas måste de ursprungliga värdena vara lika med de aktuella databasvärdena (klicka om du vill visa en bild i full storlek)
Det finns olika metoder för att implementera optimistisk samtidighet (se Peter A. Brombergsoptimistiska samtidighetsuppdateringslogik för en kort titt på ett antal alternativ). Tekniken som används av SqlDataSource (samt av de ADO.NET Typed DataSets som används i vårt dataåtkomstlager) utökar WHERE satsen för att inkludera en jämförelse av alla ursprungliga värden.
UPDATE Följande instruktion uppdaterar till exempel namnet och priset på en produkt endast om de aktuella databasvärdena är lika med de värden som ursprungligen hämtades när posten uppdaterades i GridView. Parametrarna @ProductName och @UnitPrice innehåller de nya värden som angetts av användaren, medan @original_ProductName och @original_UnitPrice innehåller de värden som ursprungligen lästes in i GridView när knappen Redigera klickades:
UPDATE Products SET
ProductName = @ProductName,
UnitPrice = @UnitPrice
WHERE
ProductID = @original_ProductID AND
ProductName = @original_ProductName AND
UnitPrice = @original_UnitPrice
Som vi ser i den här självstudien är det lika enkelt att aktivera optimistisk samtidighetskontroll med SqlDataSource som att kontrollera en kryssruta.
Steg 1: Skapa en SqlDataSource som stöder optimistisk samtidighet
Börja med att öppna OptimisticConcurrency.aspx sidan från SqlDataSource mappen. Dra en SqlDataSource-kontroll från verktygslådan till designern och ange dess ID egenskap till ProductsDataSourceWithOptimisticConcurrency. Klicka sedan på länken Konfigurera datakälla från kontrollens smarta tagg. Från den första skärmen i guiden väljer du att arbeta med NORTHWINDConnectionString och klickar på Nästa.
Bild 4: Välj att arbeta med NORTHWINDConnectionString (Klicka om du vill visa en bild i full storlek)
I det här exemplet lägger vi till en GridView som gör det möjligt för användare att redigera Products tabellen. Från skärmen Konfigurera välj instruktionen väljer du tabellen Products från listrutan och väljer kolumnerna ProductID, ProductName, UnitPrice och Discontinued som visas i figur 5.
Bild 5: Från tabellen Products returnerar du kolumnerna ProductID, ProductName, UnitPriceoch Discontinued (Klicka om du vill visa en bild i full storlek)
När du har valt kolumnerna klickar du på knappen Avancerat för att visa dialogrutan Avancerade ALTERNATIV för SQL-generering. Markera kryssrutorna Generera INSERT, UPDATE och DELETE samt Använd optimistisk samtidighet och klicka på OK (se bild 1 för en skärmbild). Slutför guiden genom att klicka på Nästa och sedan på Slutför.
När du har slutfört guiden Konfigurera datakälla, ta en stund för att undersöka DeleteCommand- och UpdateCommand-egenskaperna samt DeleteParameters- och UpdateParameters-samlingarna. Det enklaste sättet att göra detta är att klicka på fliken Källa i det nedre vänstra hörnet för att se sidans deklarativa syntax. Där hittar du värdet 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
Med sju parametrar i UpdateParameters samlingen:
<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>
På samma sätt bör egenskapen DeleteCommand och DeleteParameters samlingen se ut så här:
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>
Förutom att utöka klausulerna för egenskaperna WHERE och UpdateCommand (och lägga till ytterligare parametrar i respektive parameterkollektioner) justerar alternativet Använd optimistisk samtidighet två andra egenskaper:
- Ändrar egenskapen
ConflictDetectionfrånOverwriteChanges(standardvärdet) tillCompareAllValues -
OldValuesParameterFormatStringÄndrar egenskapen från {0} (standard) till original_{0} .
När datawebbkontrollen anropar Update() eller Delete()-metoden från SqlDataSource, skickas de ursprungliga värdena. Om egenskapen SqlDataSource är ConflictDetection inställd på CompareAllValuesläggs dessa ursprungliga värden till i kommandot. Egenskapen OldValuesParameterFormatString innehåller det namngivningsmönster som används för dessa ursprungliga värdeparametrar. Guiden Konfigurera datakälla använder original_{0} och namnger varje ursprunglig parameter i UpdateCommand egenskaperna och DeleteCommandUpdateParameters och och DeleteParameters samlingarna i enlighet med detta.
Anmärkning
Eftersom vi inte använder SqlDataSource-kontrollens infogningskapacitet kan du ta bort InsertCommand-egenskapen och dess InsertParameters-samling.
Korrekt hantering avNULLvärden
Tyvärr UPDATE förhöjda DELETE instruktioner och -instruktioner som genereras automatiskt av guiden Konfigurera datakälla när optimistisk samtidighet används med poster som innehåller NULL värden. För att se varför kan du överväga våra 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
Kolumnen UnitPrice i Products tabellen kan innehålla NULL värden. Om en viss post har ett NULL-värde för UnitPrice, kommer alltid satsdelen WHERE[UnitPrice] = @original_UnitPrice att utvärderas som False eftersom alltid returnerar False. Därför går det inte att redigera eller ta bort poster som innehåller NULL värden eftersom UPDATE instruktionssatserna DELETE och WHERE inte returnerar några rader som ska uppdateras eller tas bort.
Anmärkning
Den här buggen rapporterades först till Microsoft i juni 2004 i SqlDataSource genererar felaktiga SQL-instruktioner och är enligt uppgift schemalagd att åtgärdas i nästa version av ASP.NET.
För att åtgärda detta måste vi manuellt uppdatera satserna WHERE i både UpdateCommand egenskaperna och DeleteCommand för alla kolumner som kan ha NULL värden. I allmänhet ändrar du [ColumnName] = @original_ColumnName till:
(
([ColumnName] IS NULL AND @original_ColumnName IS NULL)
OR
([ColumnName] = @original_ColumnName)
)
Den här ändringen kan göras direkt via deklarativ markering, via alternativen UpdateQuery eller DeleteQuery från fönstret Egenskaper, eller via flikarna UPDATE och DELETE i alternativet Ange en anpassad SQL-instruktion eller lagrad procedur i guiden Konfigurera datakälla. Återigen måste den här ändringen göras för varje kolumn i UpdateCommand och DeleteCommand s-satsen WHERE som kan innehålla NULL värden.
Om du tillämpar detta på vårt exempel resulterar det i följande ändrade UpdateCommand värden och DeleteCommand värden:
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
Steg 2: Lägga till en GridView med alternativ för redigering och borttagning
Med SqlDataSource konfigurerat för att stödja optimistisk samtidighet är allt som återstår att lägga till en datawebbkontroll på sidan som använder den här samtidighetskontrollen. I den här självstudien ska vi lägga till en GridView som innehåller både redigerings- och borttagningsfunktioner. Det gör du genom att dra en GridView från verktygslådan till designern och ställa in den ID på Products. Från GridViews smarta tagg binder du den till SqlDataSource-kontrollen ProductsDataSourceWithOptimisticConcurrency som lades till i steg 1. Kontrollera slutligen alternativen Aktivera redigering och Aktivera borttagning från den smarta taggen.
Bild 6: Binda GridView till SqlDataSource och Aktivera redigering och borttagning (Klicka om du vill visa en bild i full storlek)
När du har lagt till GridView konfigurerar du dess utseende genom att ta bort ProductID BoundField, ändra ProductName egenskapen BoundField till HeaderText Product och uppdatera UnitPrice BoundField så att dess HeaderText egenskap helt enkelt är Price. Helst skulle vi förbättra redigeringsgränssnittet så att det innehåller en RequiredFieldValidator för ProductName-värdet och en CompareValidator för UnitPrice-värdet (för att säkerställa att det är ett korrekt formaterat numeriskt värde). Mer detaljerad information om hur du anpassar GridView-redigeringsgränssnittet finns i självstudien Anpassa datamodifieringsgränssnittet .
Anmärkning
Rutnätsvyns vytillstånd måste vara aktiverat eftersom de ursprungliga värdena som skickades från GridView till SqlDataSource lagras i visningstillstånd.
När du har gjort dessa ändringar i GridView bör deklarativ markering för GridView och SqlDataSource se ut ungefär så här:
<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>
Om du vill se den optimistiska samtidighetskontrollen i praktiken öppnar du två webbläsarfönster och läser in OptimisticConcurrency.aspx sidan i båda. Klicka på redigera knapparna för den första produkten i båda webbläsarna. Ändra produktnamnet i en webbläsare och klicka på Uppdatera. Webbläsaren kommer att genomföra en postback och GridView återgår till läget före redigering och visar det nya produktnamnet för posten som nyss redigerats.
I det andra webbläsarfönstret ändrar du priset (men lämnar produktnamnet som ursprungligt värde) och klickar på Uppdatera. Vid efterretur återgår rutnätet till förredigeringsläget, men ändringen av priset registreras inte. Den andra webbläsaren visar samma värde som den första: det nya produktnamnet med det gamla priset. Ändringarna som gjordes i det andra webbläsarfönstret gick förlorade. Dessutom förlorades ändringarna ganska tyst, eftersom det inte fanns något undantag eller meddelande som indikerar att en samtidighetsöverträdelse just inträffade.
Bild 7: Ändringarna i det andra webbläsarfönstret förlorades tyst (klicka om du vill visa en bild i full storlek)
Anledningen till varför ändringarna i den andra webbläsaren inte genomfördes var att instruktionens sats filtrerade bort alla poster och därför inte påverkade några rader. Låt oss titta på UPDATE -uttalandet igen:
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
När det andra webbläsarfönstret uppdaterar posten, matchar inte det ursprungliga produktnamnet som anges i WHERE-klausulen det befintliga produktnamnet (eftersom det ändrades av den första webbläsaren). Därför returnerar uttrycket [ProductName] = @original_ProductName False, och UPDATE påverkar inte några poster.
Anmärkning
Borttagning fungerar på samma sätt. Med två webbläsarfönster öppna börjar du med att redigera en viss produkt med en och sedan spara ändringarna. När du har sparat ändringarna i den ena webbläsaren klickar du på knappen Ta bort för samma produkt i den andra. Eftersom de ursprungliga värdena inte matchar i instruktionens DELETE s-sats WHERE misslyckas borttagningen tyst.
Från slutanvändarens perspektiv i det andra webbläsarfönstret, efter att ha klickat på knappen Uppdatera, återgår rutnätet till förredigeringsläget, men deras ändringar förlorades. Det finns dock ingen visuell feedback om att deras ändringar inte fastnade. Helst, om en användares ändringar går förlorade till en samtidighetsöverträdelse, meddelar vi dem och kanske håller rutnätet i redigeringsläge. Låt oss titta på hur du kan åstadkomma detta.
Steg 3: Fastställa när en samtidighetsöverträdelse har inträffat
Eftersom en samtidighetsöverträdelse avvisar de ändringar som en har gjort, skulle det vara trevligt att varna användaren när en samtidighetsöverträdelse har inträffat. Om du vill varna användaren lägger vi till en etikettwebbkontroll överst på sidan med namnet ConcurrencyViolationMessage vars Text egenskap visar följande meddelande: Du har försökt uppdatera eller ta bort en post som uppdaterades samtidigt av en annan användare. Granska den andra användarens ändringar och gör sedan om uppdateringen eller borttagningen. Ange egenskapen för Etikettkontroll till CssClass Varning, vilket är en CSS-klass definierad i Styles.css och visar text i ett rött, kursivt, fetstilt och stort teckensnitt. Ställ slutligen in egenskaperna för etikett Visible och EnableViewState till False. Detta döljer etiketten förutom endast de postbacks där vi uttryckligen anger dess Visible egenskap till True.
Bild 8: Lägg till en etikettkontroll på sidan för att visa varningen (Klicka om du vill visa en bild i full storlek)
När du utför en uppdatering eller borttagning utlöses GridViews RowUpdated och RowDeleted händelsehanterarna efter att datakällans kontroll har utfört den begärda uppdateringen eller borttagningen. Vi kan avgöra hur många rader som påverkades av åtgärden från dessa händelsehanterare. Om noll rader påverkas vill vi visa etiketten ConcurrencyViolationMessage .
Skapa en händelsehanterare för både RowUpdated händelserna och RowDeleted och lägg till följande 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
I båda händelsehanterarna kontrollerar vi e.AffectedRows egenskapen, och om den är lika med 0 anger vi ConcurrencyViolationMessage Label s Visible egenskap till True.
RowUpdated I händelsehanteraren instruerar vi även GridView att hålla sig i redigeringsläge genom att ställa in egenskapen KeepInEditMode på true. När vi gör det måste vi koppla om data till rutnätet så att den andra användarens data läses in i redigeringsgränssnittet. Detta uppnås genom att anropa Metoden GridView.DataBind()
Som bild 9 visar, med dessa två händelsehanterare, visas ett mycket märkbart meddelande när en samtidighetsöverträdelse inträffar.
Bild 9: Ett meddelande visas vid en samtidighetsöverträdelse (Klicka för att visa bilden i fullstorlek)
Sammanfattning
När du skapar ett webbprogram där flera samtidiga användare kan redigera samma data är det viktigt att överväga alternativ för samtidighetskontroll. Som standard använder ASP.NET datawebbkontroller och datakällkontroller inte någon samtidighetskontroll. Som vi såg i den här självstudien är det relativt snabbt och enkelt att implementera optimistisk samtidighetskontroll med SqlDataSource. SqlDataSource hanterar det mesta av benarbetet för att lägga till utökade WHERE satser i autogenererade UPDATE- och DELETE-instruktioner, men det finns några subtiliteter i hanterandet av värdekolumnerna i NULL, och som beskrivs i avsnittet "Hantera NULL värden korrekt".
Den här handledningen avslutar vår genomgång av SqlDataSource. Våra återstående handledningar återgår till att arbeta med data genom att använda ObjectDataSource och arkitektur med flera nivåer.
Lycka till med programmerandet!
Om författaren
Scott Mitchell, författare till sju ASP/ASP.NET-böcker och grundare av 4GuysFromRolla.com, har arbetat med Microsofts webbtekniker sedan 1998. Scott arbetar som oberoende konsult, tränare och författare. Hans senaste bok är Sams Teach Yourself ASP.NET 2.0 på 24 timmar. Han kan nås på mitchell@4GuysFromRolla.com.