首先要说明的是,该方法仅对将session存放于sql server中有效。很多人说session存放于sql server中效率太低,我觉得这只能说低一些,不能说太低。这其中的好处更大一些,如果将session存放在进程内,应用程序一重启就没了,有时候很麻烦;存放在进程外和存放在数据库中效率几乎一样。
这个类是从.net framework的源码里得到的,删除了updatesession的部分,只保留了获得session的部分,可以单独作为一个类或者放在类中做私有类使用。
#Region
"
分析Session的私有类"
Private Class altSerialization Class altSerialization
' Methods
Shared Sub New()Sub New()
Dim typeArray1 As Type() = New Type(21) {}
typeArray1(1) = GetType(String)
typeArray1(2) = GetType(Integer)
typeArray1(3) = GetType(Boolean)
typeArray1(4) = GetType(DateTime)
typeArray1(5) = GetType(Decimal)
typeArray1(6) = GetType(Byte)
typeArray1(7) = GetType(Char)
typeArray1(8) = GetType(Single)
typeArray1(9) = GetType(Double)
typeArray1(10) = GetType(SByte)
typeArray1(11) = GetType(Short)
typeArray1(12) = GetType(Long)
typeArray1(13) = GetType(UInt16)
typeArray1(14) = GetType(UInt32)
typeArray1(15) = GetType(UInt64)
typeArray1(16) = GetType(TimeSpan)
typeArray1(17) = GetType(Guid)
typeArray1(18) = GetType(IntPtr)
typeArray1(19) = GetType(UIntPtr)
altSerialization.s_serializedTypes = typeArray1
End Sub
Private Sub New()Sub New()
End Sub
Public Shared Function ReadValueFromStream()Function ReadValueFromStream(ByVal reader As BinaryReader) As Object
Dim numArray1 As Integer()
Dim num1 As Integer
Dim buffer1 As Byte()
Dim formatter1 As System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim obj1 As Object = Nothing
Select Case CType(reader.ReadByte, TypeID)
Case CType(CType(CType(1, TypeID), TypeID), TypeID)
Return reader.ReadString
Case CType(CType(CType(2, TypeID), TypeID), TypeID)
Return reader.ReadInt32
Case CType(CType(CType(3, TypeID), TypeID), TypeID)
Return reader.ReadBoolean
Case CType(CType(CType(4, TypeID), TypeID), TypeID)
Return New DateTime(reader.ReadInt64)
Case CType(CType(CType(5, TypeID), TypeID), TypeID)
numArray1 = New Integer(4) {}
num1 = 0
GoTo Label_00CA
Case CType(CType(CType(6, TypeID), TypeID), TypeID)
Return reader.ReadByte
Case CType(CType(CType(7, TypeID), TypeID), TypeID)
Return reader.ReadChar
Case CType(CType(CType(8, TypeID), TypeID), TypeID)
Return reader.ReadSingle
Case CType(CType(CType(9, TypeID), TypeID), TypeID)
Return reader.ReadDouble
Case CType(CType(CType(10, TypeID), TypeID), TypeID)
Return reader.ReadSByte
Case CType(CType(CType(11, TypeID), TypeID), TypeID)
Return reader.ReadInt16
Case CType(CType(CType(12, TypeID), TypeID), TypeID)
Return reader.ReadInt64
Case CType(CType(CType(13, TypeID), TypeID), TypeID)
Return reader.ReadUInt16
Case CType(CType(CType(14, TypeID), TypeID), TypeID)
Return reader.ReadUInt32
Case CType(CType(CType(15, TypeID), TypeID), TypeID)
Return reader.ReadUInt64
Case CType(CType(CType(16, TypeID), TypeID), TypeID)
Return New TimeSpan(reader.ReadInt64)
Case CType(CType(CType(17, TypeID), TypeID), TypeID)
buffer1 = reader.ReadBytes(16)
Return New Guid(buffer1)
Case CType(CType(CType(18, TypeID), TypeID), TypeID)
If (IntPtr.Size = 4) Then
Return New IntPtr(reader.ReadInt32)
End If
GoTo Label_01D3
Case CType(CType(CType(19, TypeID), TypeID), TypeID)
If (UIntPtr.Size = 4) Then
Return New UIntPtr(reader.ReadUInt32)
End If
GoTo Label_0201
Case CType(CType(CType(20, TypeID), TypeID), TypeID)
formatter1 = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Return formatter1.Deserialize(reader.BaseStream)
Case CType(CType(CType(21, TypeID), TypeID), TypeID)
GoTo Label_022B
End Select
Return obj1
Label_00BD:
numArray1(num1) = reader.ReadInt32
num1 = (num1 + 1)
Label_00CA:
If (num1 < 4) Then
GoTo Label_00BD
End If
Return New Decimal(numArray1)
Label_01D3:
Return New IntPtr(reader.ReadInt64)
Label_0201:
Return New UIntPtr(reader.ReadUInt64)
Label_022B:
Return Nothing
End Function
' Fields
Private Shared s_serializedTypes As Type()
' Nested Types
Private Enum TypeIDEnum TypeID
' Fields
[Boolean] = 3
[Byte] = 6
[Char] = 7
DateTime = 4
[Decimal] = 5
[Double] = 9
Guid = 17
Int16 = 11
Int32 = 2
Int64 = 12
IntPtr = 18
[Null] = 21
[Object] = 20
SByte = 10
[Single] = 8
[String] = 1
TimeSpan = 16
UInt16 = 13
UInt32 = 14
UInt64 = 15
UIntPtr = 19
End Enum
End Class
# End Region
Private Class altSerialization Class altSerialization
' Methods
Shared Sub New()Sub New()
Dim typeArray1 As Type() = New Type(21) {}
typeArray1(1) = GetType(String)
typeArray1(2) = GetType(Integer)
typeArray1(3) = GetType(Boolean)
typeArray1(4) = GetType(DateTime)
typeArray1(5) = GetType(Decimal)
typeArray1(6) = GetType(Byte)
typeArray1(7) = GetType(Char)
typeArray1(8) = GetType(Single)
typeArray1(9) = GetType(Double)
typeArray1(10) = GetType(SByte)
typeArray1(11) = GetType(Short)
typeArray1(12) = GetType(Long)
typeArray1(13) = GetType(UInt16)
typeArray1(14) = GetType(UInt32)
typeArray1(15) = GetType(UInt64)
typeArray1(16) = GetType(TimeSpan)
typeArray1(17) = GetType(Guid)
typeArray1(18) = GetType(IntPtr)
typeArray1(19) = GetType(UIntPtr)
altSerialization.s_serializedTypes = typeArray1
End Sub
Private Sub New()Sub New()
End Sub
Public Shared Function ReadValueFromStream()Function ReadValueFromStream(ByVal reader As BinaryReader) As Object
Dim numArray1 As Integer()
Dim num1 As Integer
Dim buffer1 As Byte()
Dim formatter1 As System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Dim obj1 As Object = Nothing
Select Case CType(reader.ReadByte, TypeID)
Case CType(CType(CType(1, TypeID), TypeID), TypeID)
Return reader.ReadString
Case CType(CType(CType(2, TypeID), TypeID), TypeID)
Return reader.ReadInt32
Case CType(CType(CType(3, TypeID), TypeID), TypeID)
Return reader.ReadBoolean
Case CType(CType(CType(4, TypeID), TypeID), TypeID)
Return New DateTime(reader.ReadInt64)
Case CType(CType(CType(5, TypeID), TypeID), TypeID)
numArray1 = New Integer(4) {}
num1 = 0
GoTo Label_00CA
Case CType(CType(CType(6, TypeID), TypeID), TypeID)
Return reader.ReadByte
Case CType(CType(CType(7, TypeID), TypeID), TypeID)
Return reader.ReadChar
Case CType(CType(CType(8, TypeID), TypeID), TypeID)
Return reader.ReadSingle
Case CType(CType(CType(9, TypeID), TypeID), TypeID)
Return reader.ReadDouble
Case CType(CType(CType(10, TypeID), TypeID), TypeID)
Return reader.ReadSByte
Case CType(CType(CType(11, TypeID), TypeID), TypeID)
Return reader.ReadInt16
Case CType(CType(CType(12, TypeID), TypeID), TypeID)
Return reader.ReadInt64
Case CType(CType(CType(13, TypeID), TypeID), TypeID)
Return reader.ReadUInt16
Case CType(CType(CType(14, TypeID), TypeID), TypeID)
Return reader.ReadUInt32
Case CType(CType(CType(15, TypeID), TypeID), TypeID)
Return reader.ReadUInt64
Case CType(CType(CType(16, TypeID), TypeID), TypeID)
Return New TimeSpan(reader.ReadInt64)
Case CType(CType(CType(17, TypeID), TypeID), TypeID)
buffer1 = reader.ReadBytes(16)
Return New Guid(buffer1)
Case CType(CType(CType(18, TypeID), TypeID), TypeID)
If (IntPtr.Size = 4) Then
Return New IntPtr(reader.ReadInt32)
End If
GoTo Label_01D3
Case CType(CType(CType(19, TypeID), TypeID), TypeID)
If (UIntPtr.Size = 4) Then
Return New UIntPtr(reader.ReadUInt32)
End If
GoTo Label_0201
Case CType(CType(CType(20, TypeID), TypeID), TypeID)
formatter1 = New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
Return formatter1.Deserialize(reader.BaseStream)
Case CType(CType(CType(21, TypeID), TypeID), TypeID)
GoTo Label_022B
End Select
Return obj1
Label_00BD:
numArray1(num1) = reader.ReadInt32
num1 = (num1 + 1)
Label_00CA:
If (num1 < 4) Then
GoTo Label_00BD
End If
Return New Decimal(numArray1)
Label_01D3:
Return New IntPtr(reader.ReadInt64)
Label_0201:
Return New UIntPtr(reader.ReadUInt64)
Label_022B:
Return Nothing
End Function
' Fields
Private Shared s_serializedTypes As Type()
' Nested Types
Private Enum TypeIDEnum TypeID
' Fields
[Boolean] = 3
[Byte] = 6
[Char] = 7
DateTime = 4
[Decimal] = 5
[Double] = 9
Guid = 17
Int16 = 11
Int32 = 2
Int64 = 12
IntPtr = 18
[Null] = 21
[Object] = 20
SByte = 10
[Single] = 8
[String] = 1
TimeSpan = 16
UInt16 = 13
UInt32 = 14
UInt64 = 15
UIntPtr = 19
End Enum
End Class
# End Region
使用它的核心代码(.net framework对我抛弃的几个bool以及数值进行了一些判断,我没有深究,有朋友研究过的请指点一下。)
Dim
sql
As
String
=
"
select * from ASPState..ASPStateTempSessions where datediff(minute, LockDateLocal, GetDate()) < 20"
Dim dt As New DataTable
DataDriver.GetRows(sql, dt) ' 该方法用于从数据库中获取一个数据集,可参考我的文章:http://www.cnblogs.com/squirrel_sc/archive/2004/11/04/60447.html
Dim sTemp As String
Dim obj As Object
Dim st As New MemoryStream
Dim str As New BinaryReader(st)
Dim col As New System.Collections.Specialized.NameValueCollection
For i As Integer = 0 To dt.Rows.Count - 1
Dim bTemp() As Byte = dt.Rows(i)( " SessionItemShort " )
st.SetLength( 0 )
st. Write (bTemp, 0 , bTemp.Length)
st. Seek ( 0 , SeekOrigin.Begin)
str .ReadInt32()
str .ReadBoolean()
str .ReadBoolean()
str .ReadBoolean()
Dim iCount As Integer = str .ReadInt32
Dim btTemp As Byte
str .ReadInt32()
For k As Integer = 0 To iCount - 1
sTemp = str .ReadString
obj = altSerialization.ReadValueFromStream( str )
' obj就是sTemp这个session名字对应的内容,它的类型不定。在这里对其进行操作就可以了
Next
Next
str .Close()
st.Close()
Dim dt As New DataTable
DataDriver.GetRows(sql, dt) ' 该方法用于从数据库中获取一个数据集,可参考我的文章:http://www.cnblogs.com/squirrel_sc/archive/2004/11/04/60447.html
Dim sTemp As String
Dim obj As Object
Dim st As New MemoryStream
Dim str As New BinaryReader(st)
Dim col As New System.Collections.Specialized.NameValueCollection
For i As Integer = 0 To dt.Rows.Count - 1
Dim bTemp() As Byte = dt.Rows(i)( " SessionItemShort " )
st.SetLength( 0 )
st. Write (bTemp, 0 , bTemp.Length)
st. Seek ( 0 , SeekOrigin.Begin)
str .ReadInt32()
str .ReadBoolean()
str .ReadBoolean()
str .ReadBoolean()
Dim iCount As Integer = str .ReadInt32
Dim btTemp As Byte
str .ReadInt32()
For k As Integer = 0 To iCount - 1
sTemp = str .ReadString
obj = altSerialization.ReadValueFromStream( str )
' obj就是sTemp这个session名字对应的内容,它的类型不定。在这里对其进行操作就可以了
Next
Next
str .Close()
st.Close()
使用实例:
该方法用于遍历所有session,形成在线用户列表。由于这个操作可能效率较低,所以把结果在内存中缓存1分钟。用户名存在名为UserName的session中。
Private
Shared
_onlineUserList
As
ArrayList
Private Shared _onlineUserUpdateTime As DateTime
Public Shared Function GetOnlineUserList() Function GetOnlineUserList() As ArrayList
If (_onlineUserList Is Nothing) Then
_onlineUserList = New ArrayList
_onlineUserUpdateTime = Now
End If
If (_onlineUserUpdateTime.AddMinutes(1) < Now OrElse _onlineUserList.Count = 0) Then
_onlineUserList.Clear()
Dim sql As String = "select * from ASPState..ASPStateTempSessions where datediff(minute, LockDateLocal, GetDate()) < 20"
Dim dt As New DataTable
DataDriver.GetRows(sql, dt)
Dim sTemp As String
Dim obj As Object
Dim st As New MemoryStream
Dim str As New BinaryReader(st)
Dim col As New System.Collections.Specialized.NameValueCollection
For i As Integer = 0 To dt.Rows.Count - 1
Dim bTemp() As Byte = dt.Rows(i)("SessionItemShort")
st.SetLength(0)
st.Write(bTemp, 0, bTemp.Length)
st.Seek(0, SeekOrigin.Begin)
str.ReadInt32()
str.ReadBoolean()
str.ReadBoolean()
str.ReadBoolean()
Dim iCount As Integer = str.ReadInt32
Dim btTemp As Byte
str.ReadInt32()
For k As Integer = 0 To iCount - 1
sTemp = str.ReadString
obj = altSerialization.ReadValueFromStream(str)
If (sTemp = "UserName" AndAlso _onlineUserList.BinarySearch(obj) < 0) Then
_onlineUserList.Add(DirectCast(obj, String))
Exit For
End If
Next
Next
str.Close()
st.Close()
_onlineUserUpdateTime = Now
End If
Return _onlineUserList
End Function
Private Shared _onlineUserUpdateTime As DateTime
Public Shared Function GetOnlineUserList() Function GetOnlineUserList() As ArrayList
If (_onlineUserList Is Nothing) Then
_onlineUserList = New ArrayList
_onlineUserUpdateTime = Now
End If
If (_onlineUserUpdateTime.AddMinutes(1) < Now OrElse _onlineUserList.Count = 0) Then
_onlineUserList.Clear()
Dim sql As String = "select * from ASPState..ASPStateTempSessions where datediff(minute, LockDateLocal, GetDate()) < 20"
Dim dt As New DataTable
DataDriver.GetRows(sql, dt)
Dim sTemp As String
Dim obj As Object
Dim st As New MemoryStream
Dim str As New BinaryReader(st)
Dim col As New System.Collections.Specialized.NameValueCollection
For i As Integer = 0 To dt.Rows.Count - 1
Dim bTemp() As Byte = dt.Rows(i)("SessionItemShort")
st.SetLength(0)
st.Write(bTemp, 0, bTemp.Length)
st.Seek(0, SeekOrigin.Begin)
str.ReadInt32()
str.ReadBoolean()
str.ReadBoolean()
str.ReadBoolean()
Dim iCount As Integer = str.ReadInt32
Dim btTemp As Byte
str.ReadInt32()
For k As Integer = 0 To iCount - 1
sTemp = str.ReadString
obj = altSerialization.ReadValueFromStream(str)
If (sTemp = "UserName" AndAlso _onlineUserList.BinarySearch(obj) < 0) Then
_onlineUserList.Add(DirectCast(obj, String))
Exit For
End If
Next
Next
str.Close()
st.Close()
_onlineUserUpdateTime = Now
End If
Return _onlineUserList
End Function
关于设置:
我使用的是信任连接,在XP下就是aspnet用户,ASPState数据库就是它的,所以访问数据库的权限上没有问题。session存放在sql server中要使用持久的那种,如果是存放在tempDb中的,一重启机器后,权限就要重新设置,很苦恼。