ASP数据缓存类(自动判断缓存过期,模拟Recordset类)
应用场景:对于某些读取数据次数较多,sql性能不太好或网络延迟影响较大的页面.
使用方法:包含入本类库文件,初始化并设定好参数,之后的sql查询都通过本类执行,并对每个查询指定不同的缓存名称
缓存原理:调用查询时先根据缓存名称判断Application中是否有指定的缓存,数据是否合法,是否过期,没有过期就读取Application中的缓存内容,并模拟成Rs对象返回
如果缓存不存在或已过期,则使用指定的Connection链接查询,并将结果作为二维数组写入缓存,待下次查询使用,将当次查询的数据模拟为Rs对象返回。
示例代码:
Dim Data, rs Set Data=new xDataCache Data.ActiveConnection=conn Data.CacheTime=100 Set rs=Data.Exec("SELECT TOP 10 * FROM NEWS","news") Do Until rs.EOF Response.Write rs("ID")&":"& rs("title")&"<br />" rs.MoveNext Loop
类原码(里面包含两个类,一个缓存类,一个将二维数组模拟为Rs的类):
'+++++++++++++++++++++++++++++++++++ 'ASP数据缓存 '可按设定直接执行SQL语句,并将结果以二维数组存保存到application '返回一个类Recordset对象 'shirne@126.com 'http://www.shirne.com '+++++++++++++++++++++++++++++++++++ Class xDataCache Public PRE '缓存前缀 Private PARAM '缓存参数后缀 '缓存单位 '建议使用 h, m, s,默认 s Public Unit '默认缓存时间,默认500 Public CacheTime '使用默认缓存时间时为了避免多个缓存同时过期,加入一个时间误差,默认.1 Public Ratio Private conn Private Sub Class_Initialize PRE = "data_" PARAM = "_param" CacheTime = 500 Unit = "s" Ratio = .1 End Sub Private Sub Class_Terminate End Sub '指定数据库链接 Public Property Let ActiveConnection(con) Set conn = con End Property '使用默认时间缓存 Public Function Exec(sql, cName) Set Exec = Execute(sql, cName, Null) End Function '执行sql,指定缓存时间,指定Null将使用默认缓存时间 Public Function [Execute](sql, cName, cTime) '存储辅助参数,Array(缓存时间,超时时间,字段数组) Dim pam, rs, arrData pam = Application(PRE & cName & PARAM) arrData = Application(PRE & cName) Set rs=New ArrayToRs If IsArray(pam) And IsArray(arrData) Then If UBound(pam)=2 Then If IsNumeric(cTime) And cTime<>"" Then pam(1)=Int(cTime) If IsDate(pam(0)) And ( IsNumeric(pam(1)) And pam(1)<>"" ) Then If DateDiff(Unit, pam(0), Now)<pam(1) Then rs.Fields = pam(2) rs.Data = arrData Set Execute = rs Exit Function End If End If End If End If '读取数据 Dim flds, ERs, Field Set ERs=conn.Execute(sql) If ERs.EOF Then '不操作 Else '从结果中取字段 flds = "" For Each Field In ERs.Fields flds = flds &","&Field.Name Next flds = Mid(flds,2) rs.Fields = flds rs.Data = ERs.getRows() Application.Lock() Application(PRE & cName & PARAM)=Array(Now,getCacheTime(cTime),flds) Application(PRE & cName )=rs.Data Application.UnLock() End If Set Execute = rs End Function Private Function getCacheTime( dTime) If IsNumeric(dTime) Then getCacheTime = Int(dTime) Else Randomize getCacheTime = CacheTime + CacheTime * Ratio * (FormatNumber(Rnd,2)+.01) End If End Function '清除缓存,是否清除全部,还是只清除带前缀的 Public Sub Clear(bol) If bol Then Application.Contents.RemoveAll() Else Dim key, l l = Len(PRE) Application.Lock() For Each key In Application.Contents If Left(key,l)=PRE Then Application.Contents.Remove(key) End If Next Application.UnLock() End If End Sub End Class '将Recordset返回的二维数组重新模拟为Rs Class ArrayToRs Private dicFld Private arrData Private Count Private Position Private pEOF Private pBOF Private Sub Class_Initialize Set dicFld=Server.CreateObject("Scripting.Dictionary") dicFld.CompareMode=1 Count = 0 Position= 0 pEOF = True pBOF = True End Sub '设定字段名称 Public Property Let Fields( f) Dim i, j dicFld.RemoveAll If IsObject(f) Then i=0 For Each j In f dicFld.Add j, i i = i + 1 Next Else If TypeName(f) = "String" Then If InStr(f," ")>0 Then f = Replace(f," ","") If InStr(f,"[")>0 Then f = Replace(Replace(f,"[",""),"]","") f = Split(f,",") End If If IsArray(f) Then For i=0 To UBound(f) dicFld.Add f(i),i Next End If End If End Property Public Property Get Fields( ) Set Fields = dicFld End Property Public Property Let Data( d) If IsArray(d) Then arrData = d Count = UBound(d,2)+1 Position = 1 pEOF = False pBOF = False End If End Property Public Property Get Data() Data = arrData End Property Public Default Property Get Item( ByVal key) If pBOF Or pEOF Then Exit Property End If If IsNumeric(key) Then key = Int(key) Else If dicFld.Exists(key) Then key = dicFld(key) Else Exit Property End If End If Item = arrData(key,Position-1) End Property Public Property Let Item( key, val) If pBOF Or pEOF Then Exit Property End If If IsNumeric(key) Then key = Int(key) Else If dicFld.Exists(key) Then key = dicFld(key) Else Exit Property End If End If arrData(key,Position-1) = val End Property Public Property Get BOF BOF = pBOF End Property Public Property Get EOF EOF = pEOF End Property Public Property Get RecordCount RecordCount = Count End Property Public Property Let AbsolutePosition( p) If p>0 And p<=Count Then Position = p Else '错误,超出记录集 End If End Property Public Property Get AbsolutePosition( ) AbsolutePosition = Position End Property '移动记录位置 Public Sub Move( c) If Count>0 Then pEOF = False pBOF = False Position = Position + c If Position<1 Then Position = 0 pBOF = True ElseIf Position>Count Then Position = Count + 1 pEOF = True End If End If End Sub Public Sub MovePrevious If Not pBOF Then Position = Position-1 If Position<1 Then pBOF = True End If End If End Sub Public Sub MoveNext If Not pEOF Then Position = Position+1 If Position>Count Then pEOF = True End If End If End Sub Public Sub MoveFirst If Count>0 Then Position = 1 If pEOF = True Then pEOF = False End If If pBOF=True Then pBOF = False End If End If End Sub Public Sub MoveLast Position = Count If Count>0 Then If pBOF=True Then pBOF = False End If If pEOF = True Then pEOF = False End If End If End Sub End Class