Avancerad cache förenklar användardatabasen
Förord
Hur många gånger har man inte ledsnat på att skriva alla dessa databasanrop. Första ska man hämta data, sen ska man cacha och sedan får man lägga ner ytterligare energi varje gång man ska uppdatera något och har man en någorlunda avancerad cache-funktion så blir det ofta att man ska in och tömma den innan man ser resultatet. Slutligen så kommer man på att det saknades 4 grejer i användardatabasen och får börja skriva om anropen, de lagrade procedurerna och cachefunktioner. Det här är litet men oerhört underlättande tips som fungerar bra för alla typer av användardatabaser, statistk på banners och mycket annat som man inte vill ska behöva anstränga databasen.Innehåll
Det hela handlar om att använda removecallbackfunktionen (från cachen) för att uppdatera användardatabasen.
I artikeln utgår jag från mig själv. Jag brukar normalt vis behöva tillgång till majoriteten av användarens data under besöket och väljer därför ofta att cacha användarens data så fort denne loggar in.
Låt oss börja med ett enkelt exempel där vi använder en typisk och traditionell databas över användarna och deras inställningar, lösenord, presentationer etc.
Funktionen ovan hämtar ett visst värde från en specifik användare. (titta inte på mitt sätt att undvika dbnull) Användarens data cachas i en datatable som hämtas på följande vis:
Här börjar det roliga. Egentligen fyller vi bara en tabell med en enda rad så vi hade kunnat skippa att returnera hela tabellen men det finns faktiskt ytterligare en anledning.
Koden ovan hämtar och fyller en taball, tabellen sparas i cachen så att vi enkelt och snabbt kan hämta användarens data utan att behöva belasta sql'n. DOCK är detta inte syftet med denna artikel utan det kommer vi till nu. I slutet av koden ovan ser ni 'onCacheRemove'. Det är här det häftiga börjar.
- Tänk lyckan att hämta data från en cachad rad så att den inte belastar sql'n och (nu kommer det bästa) att så fort cachen försvinner (eller om du själv väljer att ta bort dne) så uppdateras eventuella förändring i databasen automatiskt!
Följande rad:
onCacheRemove = New System.Web.Caching.CacheItemRemovedCallback(AddressOf updatechanges)
...påvisar att det finns en subrutin som kallas updatechanges och som skall köras om cachen är på väg att raderas (oavsett om det sker på grund av att tiden tagit slut, att det är ont om minne eller om du själv kodmässigt valt att ta bort den)
Men först ska jag visa delen som används för att uppdatera tabellen.
That is alles, den hämtar tabellen som ligger i cachen och ändrar det värde vi vill.
exempelvis updatekey(userid, "online", 1)
Och sen då? Nu finns det en tabell som innehåller ett uppdaterat värde men hur ska värdet komma tillbaka till sql'en?
Så här:
Koden ovan körs så fort det cachade värdet är på väg att försvinna. Den kolla om det skett några förändring i tabellen som låg i cashen och om det fanns så skickar den över alla förändring till sql'n.
Som du ser är det samma Stored procedure som används så det krävs inte mycket. Med dessa raden i en class så har du allt som behövs för att underhålla en hel användardatabas.
Om du uppdaterar tabellen och vill att uppdateringen ska slå igenom direkt gör du de uppdateringar du vill och sedan tar du bort cachen så uppdaterar den allt själv:
updatekey(userid, "online", 1)
updatekey(userid, "newsmail", 1)
updatekey(userid, "lastlogin", now)
Dim cachekey As String = "udt" & userid.ToString
mycache.remove(cachekey)
Slutligen ska denna lilla rad finnas med någonstans i koden för att det hela ska fungera.
/ska se tilla at fixa stavningen senare.
I artikeln utgår jag från mig själv. Jag brukar normalt vis behöva tillgång till majoriteten av användarens data under besöket och väljer därför ofta att cacha användarens data så fort denne loggar in.
Låt oss börja med ett enkelt exempel där vi använder en typisk och traditionell databas över användarna och deras inställningar, lösenord, presentationer etc.
Public Function _get(ByVal userid As Guid, ByVal getkey As String) As Object
Dim dt As DataTable = contact._get(userid)
Dim r As DataRow = dt.Rows(0)
If r.IsNull(getkey) Then
Return ""
Else
Return r(getkey)
End If
End Function
Funktionen ovan hämtar ett visst värde från en specifik användare. (titta inte på mitt sätt att undvika dbnull) Användarens data cachas i en datatable som hämtas på följande vis:
Public Shared Function _get(ByVal userid As Guid) As DataTable
Dim cachekey As String = "_udt" & userid.ToString
'Om datatable finns i cache, returnera den
If Not myCache(cachekey) Is Nothing Then
Return myCache(cachekey)
End If
'Om inte, skapa en datatable och fyll den med användarens data
'DENNA STORED PROCEDURE HÄMTAR EN HEL RAD MED select * from xx where userid=@userid
Dim dt As New DataTable
Dim sqlCONN As New SqlConnection(("ConnectionString"))
Dim CMD As SqlCommand = New SqlCommand("cache_user_v41", sqlCONN)
CMD.CommandType = CommandType.StoredProcedure
Dim myParm As SqlParameter
myParm = CMD.Parameters.Add("@userid", SqlDbType.UniqueIdentifier)
myParm.Value = USERID....
sqlCONN.Open()
Dim adapter As New SqlDataAdapter(CMD)
adapter.Fill(dt)
sqlCONN.Close()
sqlCONN.Dispose()
CMD.Dispose()
onCacheRemove = CacheItemRemovedCallback(AddressOf updatechanges)
myCache.Insert(cachekey , dt, Nothing, DateTime.Now.AddMinutes(5), _
TimeSpan.Zero, CacheItemPriority.Normal, onCacheRemove)
Return dt
End Function
Här börjar det roliga. Egentligen fyller vi bara en tabell med en enda rad så vi hade kunnat skippa att returnera hela tabellen men det finns faktiskt ytterligare en anledning.
Koden ovan hämtar och fyller en taball, tabellen sparas i cachen så att vi enkelt och snabbt kan hämta användarens data utan att behöva belasta sql'n. DOCK är detta inte syftet med denna artikel utan det kommer vi till nu. I slutet av koden ovan ser ni 'onCacheRemove'. Det är här det häftiga börjar.
- Tänk lyckan att hämta data från en cachad rad så att den inte belastar sql'n och (nu kommer det bästa) att så fort cachen försvinner (eller om du själv väljer att ta bort dne) så uppdateras eventuella förändring i databasen automatiskt!
Följande rad:
onCacheRemove = New System.Web.Caching.CacheItemRemovedCallback(AddressOf updatechanges)
...påvisar att det finns en subrutin som kallas updatechanges och som skall köras om cachen är på väg att raderas (oavsett om det sker på grund av att tiden tagit slut, att det är ont om minne eller om du själv kodmässigt valt att ta bort den)
Men först ska jag visa delen som används för att uppdatera tabellen.
Public Shared Sub updatekey(ByVal userid As Guid, _
ByVal updkey As String, ByVal newvalue As Object)
Dim cachekey As String = "udt" & userid.ToString
Dim dt As DataTable = contact._get(contactid)
Dim r As DataRow = dt.Rows(0)
r(updkey) = newvalue
End Sub
That is alles, den hämtar tabellen som ligger i cachen och ändrar det värde vi vill.
exempelvis updatekey(userid, "online", 1)
Och sen då? Nu finns det en tabell som innehåller ett uppdaterat värde men hur ska värdet komma tillbaka till sql'en?
Så här:
Private Shared Sub updatechanges(ByVal str As String, _
ByVal obj As Object, ByVal reason As System.Web.Caching.CacheItemRemovedReason)
Dim dt As DataTable = obj
If dt.GetChanges Is System.DBNull.Value Then 'datatable hade inga förändringar
Exit Sub
End If
'Datatable hade förändringar
Dim sqlCONN As New SqlConnection(("ConnectionString"))
Dim CMD As SqlCommand = New SqlCommand("cache_user_v41", sqlCONN)
CMD.CommandType = CommandType.StoredProcedure
Dim myParm As SqlParameter
myParm = CMD.Parameters.Add("@uid", SqlDbType.UniqueIdentifier)
myParm.Value = uid()
Dim command_builder As SqlCommandBuilder
sqlCONN.Open()
Dim adapter As New SqlDataAdapter(CMD)
command_builder = New SqlCommandBuilder(adapter)
'Skicka endast förändringar till sql'n och lagra dessa permanent.
adapter.Update(dt.GetChanges)
sqlCONN.Close()
sqlCONN.Dispose()
CMD.Dispose()
End Sub
Koden ovan körs så fort det cachade värdet är på väg att försvinna. Den kolla om det skett några förändring i tabellen som låg i cashen och om det fanns så skickar den över alla förändring till sql'n.
Som du ser är det samma Stored procedure som används så det krävs inte mycket. Med dessa raden i en class så har du allt som behövs för att underhålla en hel användardatabas.
Om du uppdaterar tabellen och vill att uppdateringen ska slå igenom direkt gör du de uppdateringar du vill och sedan tar du bort cachen så uppdaterar den allt själv:
updatekey(userid, "online", 1)
updatekey(userid, "newsmail", 1)
updatekey(userid, "lastlogin", now)
Dim cachekey As String = "udt" & userid.ToString
mycache.remove(cachekey)
Slutligen ska denna lilla rad finnas med någonstans i koden för att det hela ska fungera.
Private Shared onCacheRemove As System.Web.Caching.CacheItemRemovedCallback
/ska se tilla at fixa stavningen senare.
0 Kommentarer