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