ASPNL logo (1 kb)
zaterdag 17 mei 2008




Microsoft MVP

.NET Codewise Community
<< vorige | overzicht | volgende >>

Records door één gebruiker tegelijk laten wijzigen in ASP.NET

Door Michiel van Otegem
14 april 2003

Noot: Dit artikel werkt met ASP.NET, er is ook een ASP versie.

Op het web is er geen constante verbinding met een database. Als je een record wilt wijzigen, moet je het eerst opvragen, waarna de databaseverbinding gesloten wordt. Bij het opslaan wordt de database weer geopend, en wordt het record gewijzigd. Het probleem is nu dat als iemand anders tussen het opvragen van de gegevens en het opslaan hetzelfde record opvraagt met de bedoeling het te wijzigen, dat er dan geen indicatie is dat iemand anders met dat record bezig is.

Het hierboven geschetste probleem kun je oplossen door slim gebruik te maken van het Application object en het Session object. In het Application object wordt bijgehouden welke records in gebruik zijn, en in het Session object wordt bijgehouden welk record de gebruiker in gebruik heeft. Het makkelijkste is om hiervoor twee functies te maken die je op verschillende plaatsen kunt gebruiken. In ASP.NET is het handig om deze functies in een klasse op te nemen, en te voorzien van het Shared keyword (static in C#), zodat je de betreffende klasse niet hoeft te instantiëren.

Imports System
Imports System.Web

Namespace Aspnl.Util
   Public Class RecordLocks
      Shared Function LockRecord(ByVal tableName As String, ByVal primaryKey As String) As Boolean
         Dim recordLocks As ArrayList

         'Referentie naar pagina opvragen
         Dim context As HttpContext = HttpContext.Current
         If context Is Nothing Then
            Throw New Exception("Must run in a valid HTTP context")
         End If

         'Elke sessie mag lock op 1 record tegelijk
         If context.Session("RecordLock") <> "" Then
            Call UnlockRecord()
         End If

         'Alleenrecht op Application object
         context.Application.Lock()
         'Huidige locks opvragen
         Dim o As Object = context.Application("RecordLocks")
         If o Is Nothing Then
            'Nog geen locks, dus toevoegen
            recordLocks = New ArrayList()
            recordLocks.Add(tableName & "|" & primaryKey & "|")
         Else
            recordLocks = CType(context.Application("RecordLocks"), ArrayList)
            If recordLocks.IndexOf(tableName & "|" & primaryKey & "|") > -1 Then
               'Record al in gebruik
               context.Application.UnLock()
               Return False 'Lock mislukt
            Else
               'Record nog niet in gebruik, dus toevoegen
               recordLocks.Add(tableName & "|" & primaryKey & "|")
            End If
         End If

         'Locks opslaan en Application object vrijgeven
         context.Application("RecordLocks") = recordLocks
         context.Application.UnLock()

         'Lock toekennen aan deze sessie
         context.Session("RecordLock") = tableName & "|" & primaryKey & "|"

         Return True 'Lock gelukt
      End Function

      Shared Sub UnlockRecord()
         Dim recordLocks As ArrayList

         'Referentie naar pagina opvragen
         Dim context As HttpContext = HttpContext.Current
         If context Is Nothing Then
            Throw New Exception("Must run in a valid HTTP context")
         End If

         'Alleenrecht op Application object
         context.Application.Lock()

         'Huidige locks opvragen, stoppen als locks leeg zijn
         Dim o As Object = context.Application("RecordLocks")
         If o Is Nothing Then
            context.Application.UnLock()
            Return
         End If
         'Lock verwijderen
         recordLocks = CType(context.Application("RecordLocks"), ArrayList)
         recordLocks.Remove(context.Session("RecordLock"))

         'Locks opslaan, Application object vrijgeven, en lock verwijderen uit sessie
         context.Application("RecordLocks") = recordLocks
         context.Application.UnLock()
         context.Session("RecordLock") = ""
      End Sub
   End Class
End Namespace

De bovenstaande code bevat twee functies, LockRecord voor het verkrijgen van een record en UnlockRecord voor het vrijgeven van een record. LockRecord geeft True terug als het record verkregen is, en False als het record al in gebruik is door iemand anders. Zolang de Assembly van deze klasse beschikbaar is (bijvoorbeeld door die in de /bin map van de applicatie te zetten), kun je de functionaliteit gebruiken door de volledige naam (met namespace) te gebruiken. De code hieronder laat dit zien aan de hand van gebeurtenissen die je gebruikt bij het wijzigen van records via een DataGrid.

Sub dg_EditCommand(source As Object, e As DataGridCommandEventArgs)
   Dim ProductID As String = dg.DataKeys(e.Item.ItemIndex)
   If LockRecord("Products", ProductID) Then
      dg.EditItemIndex = e.Item.ItemIndex
      BindGrid()
   Else
      ErrMsg.Text = "Rij al in gebruik door andere gebruiker."
   End If
End Sub
    Sub DataGrid1_CancelCommand(source As Object, e As DataGridCommandEventArgs)
   UnlockRecord
   dg.EditItemIndex = -1
   BindGrid()
End Sub
   
Sub dg_UpdateCommand(source As Object, e As DataGridCommandEventArgs)
   'Hier record opslaan
   ...
   UnlockRecord()
End Sub

Er zit nu nog een addertje onder het gras, namelijk dat een record in gebruik blijft als iemand de browser afsluit (of naar een andere pagina gaat) voordat het record is vrijgegeven. Om dit te voorkomen moet je in ieder geval zorgen dat het gebruikte record vrijgegeven wordt als de sessie van de betreffende gebruiker verloopt. Je kunt dit doen in de Session_End gebeurtenis in global.asax.


<< vorige | ^ naar boven | overzicht | volgende >>
copyright 2000-2007 ASPNL