【原创】
ASP.NET
会话(
Session
)保存模式
作者
:
寒羽枫
(cityhunter172)
大家好,已有四个多月没写东东啦。今日抽空就说一下
Session
在
.Net v1.0/v1.1
中的存储模式。大家可在
MSDN 2003
中搜索一下
<
sessionState
>
即可看到关于
Web.config
中的
<
sessionState
>
节点元素的描述,共有
Off
、
InProc
、
StateServer
、
SQLServer
四种模式。
Off
、
InProc
分别指“不启用”、“进程内保存(默认值)”,此两种模式没啥讲的,所谓
InProc
就是把
Session
保存在
aspnet_wp.exe
(Windows 2000
解析
ASP.NET
页面所用的进程
)
或
w3wp.exe
(Win2003
的进程
)
中,一旦进程被中止或被重置,
Session
将丢失。
一、
引发
Session
丢失的几种原因
动过手写代码的人都知道,
Session
丢失是比较常见的事。以下是本人这几年所遇到的,能够引发
Session
丢失的原因,不敢说是百分百,丢失概率还是特别高的。错…,简直可以说是“相…当…”高哇
^_^"
1、
存放
Session
的电脑重启(废话,若这样都不丢,你神仙啊)
2、 模式:aspnet_wp.exe或w3wp.exe 在“任务管理器”中或其它情况下导致其进程被终止运行。
InProc
3、 模式:修改 .cs 文件后,编译了两次(只编译一次,有时不会丢失)
InProc
4、 模式:修改了Web.config
InProc
5、 模式,Windows 2003 环境:应用程序池回收、停止后重启
InProc
6、 模式:服务器上 bin 目录里的 .dll 文件被更新
InProc
以上列举的都是
InProc
模式下,容易引发解析
ASP.NET
应用程序重置的原因。是不是觉得很窝火?之前我也有这种感觉,慢慢就习惯啦,再后来就干脆不用这种模式了。于是乎,就有了使用下列两种模式的尝试,现写出来与大家一起分享。
二、
使用
StateServer
保存
Session
StateServer
模式的实质是,把
Session
存放在一个单独的进程里,此进程独立于
aspnet_wp.exe
或
w3wp.exe
。启用此服务后,在“任务管理器”中可以看到一个名为
aspnet_state.exe
的进程,下面开始说明一下设置的具体步骤:
1、
修改注册表(关键步骤,如下图)
运行
regedit
→
打开注册表
→
找到
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/aspnet_state/Parameters
节点
→
将
AllowRemoteConnection
的键值设置成“
1
”(
1
为允许,
0
代表禁止)→
设置
Port
(
端口号
)
注意事项:
a)
、若
ASP.NET State Service
正在运行,修改注册表内容后,则需要重新启动该服务
b)
、注意端口号的键值是以十六进制储存的,可以使用十进制进行修改,
42424
是默认的端口
c)
、
AllowRemoteConnection
的键值设置成“
1
”
后,意味着允许远程电脑的连接,也就是说只要知道你的服务端口,就可享用你的
ASP.NET State Service
,即把
Session
存放在你的电脑进程内,因此请大家慎用;键值为“
0
”
时,仅有
stateConnectionString
为“
tcpip=localhost: 42424”与“tcpip=127.0.0.1:42424”的情况,方可使用
ASP.NET State Service
2、
开启
ASP.NET State Service
(如下图)
右键点击“我的电脑”→
管理
→
服务与应用程序
→
服务
→
双击“
ASP.NET State Service
”
→
启动(可设为“自动”)
说明:只要安装了
.Net Framework v1.0/v1.1
,都拥有此服务。
3、
更改
Web.config
打开
Web.config
→
找到
<
sessionState
>
节点内容
<
sessionState
mode
="InProc"
stateConnectionString
="tcpip=127.0.0.1:42424"
sqlConnectionString
="data source=127.0.0.1;Trusted_Connection=yes"
cookieless
="false"
timeout
="20"
/>
→
将其改为以下内容
<
sessionState
mode
="StateServer"
stateConnectionString
="tcpip=192.168.0.2:42424"
timeout
="20"
/>
注意事项:
a)
、设成
StateServer
后,必须要有对应的
stateConnectionString
b)
、注意
IP
地址(可以是远程计算机
IP
、计算机名称、域名)与端口号,端口号需与
ASP.NET State Service
的服务端口一致
三、
将
Session
放入
SQLServer
保存
SQLServer
模式就是,把
Session
存放在
SQL Server
数据库里(注意不是
Oracle
,动动脚趾都能猜到原因啦),下面开始说明一下设置的具体步骤:
1、
启动相关的数据库服务(如图)
运行
SQL Server
服务管理器
→
启动
SQL Server
(最好设为开机自动运行)
→
启动
SQL Server Agent
服务(最好设为开机自动运行)
注意事项:
a)
、注意启动顺序,也可通过下列方式设置:
右键点击“我的电脑”→
管理
→
服务与应用程序
→
服务
→
找到“
MSSQLSERVER
”与“
SQLSERVERAGENT
”
→
启动并设置启动类型为“自动”
b)
、
SQL Server Agent
在此处的作用是清除数据库中已过期的
Session
2、
建立存放
Session
的
DataBase
运行“
SQL
查询分析器”→
使用“
sa
”或是拥有“
master
”的
db_owner
权限的用户登录数据库
→
打开查询文件
C:/WINNT/Microsoft.NET/Framework/v1.1.4322/InstallSqlState.sql
(存放在
Windows
系统目录的
.Net
安装目录下可找到)
→
直接运行该
sql
脚本
→
刷新数据库即可看到名为
ASPState
的
DataBase
3、
建立连接数据库
ASPState
的用户,并为此用户授权(此步骤可跳过)
进行此步的原因是:一是不想在
Web.config
中出现
sa
的密码;二是
tempdb
在数据库启动后仅保留
sa
一个帐号的使用权限,其余帐号的权限统统被清除,但保存
Session
又需要用到此
DataBase
;
A)
、运行
SQL Server
的企业管理器
→
展开数据库的安全性
→
右击“登录”
→
新建“登录”
→
输入“名称”
→
选择
“
SQL Server
身份验证”
→
输入“密码”
→
指定“数据库”
→
点击“数据库访问”
→
勾选
“
ASPState
”
→
选中“
db_owner
”角色
→
点击“确定”
→
再一次输入“密码”
→
点击“确定”
后即可建立
ASPState
的用户(此处建立名为“
SessionStateUser
”,密码为“
123456
”
的测试用户)
B)
、运行
SQL Server
的企业管理器
→
展开“管理”
→
展开“
SQL Server
代理”
→
右击“作业”
→
点击“新建作业”
→
输入
“名称”(此例为
GrantSessionUser
)
→
点击标签
“步骤”
→
新建
→
输入
“步骤名”(此例为
Grant01
)
→
选择数据库“
tempdb
”
→
编写
SQL
脚本“
exec
sp_adduser
'SessionStateUser'
,
'SessionUser'
,
'db_owner'
”→
确定
→
点击标签
“调度”
→
新建
→
输入
“名称”(此例为
Start01
)→
选择类型“
SQL Server
代理启动时自动启动”
→
确定
→
最后点击“确定”新增完毕
C
)、也可运行以下脚本一次性搞定以上
A
、
B
两个步骤
/******
脚本开始
******/
--
新建数据库帐号
SessionStateUser
,默认登录
ASPState
EXEC
sp_addlogin
'SessionStateUser'
,
'123456'
,
'ASPState'
use
ASPState
--
切换
DataBase
--
将
SessionStateUser
授予
db_owner
的权限
exec
sp_adduser
'SessionStateUser'
,
'SessionUser'
,
'db_owner'
use
master
--
切换
DataBase
BEGIN TRANSACTION
/******
声明变量
******/
DECLARE
@JobID
BINARY
(
16
)
DECLARE
@ReturnCode
INT
SELECT
@ReturnCode
=
0
--
若没有,则添加作业的分类
IF
(
SELECT
COUNT
(*)
FROM
msdb.dbo.
syscategories
WHERE
name
=
N
'[Uncategorized (Local)]'
) <
1
EXECUTE
msdb.dbo.sp_add_category @name
=
N
'[Uncategorized (Local)]'
--
新建作业
EXECUTE
@ReturnCode
=
msdb.dbo.sp_add_job
--
调用存储过程
sp_add_job
@job_id
=
@JobID
OUTPUT
,
--
将返回的
JobID
,赋值给变量
@job_name
=
N
'GrantSessionUser'
,
--
作业名称
@owner_login_name
= NULL,
--
默认为当前用户所有
@description
=
null,
@category_name
=
N
'[Uncategorized (Local)]'
,
--
作业分类归属
@enabled
=
1
,
--
是否启用
@notify_level_email
=
0
,
@notify_level_page
=
0
,
@notify_level_netsend
=
0
,
@notify_level_eventlog
=
0
,
@delete_level
=
0
IF
(
@@ERROR
<>
0
OR
@ReturnCode
<>
0
)
GOTO
QuitWithRollback
--
出错则回滚
--
新建步骤
EXECUTE
@ReturnCode
=
msdb.dbo.sp_add_jobstep
--
调用存储过程
sp_add_jobstep
@job_id
=
@JobID
,
--
传入刚刚新建的
JobID
@step_id
=
1
,
@step_name
=
N
'Grant01'
,
--
步骤名称
@command
=
N
'exec sp_adduser ''SessionStateUser'', ''SessionUser'' ,''db_owner''',
--
需要执行的
SQL
脚本(注意用两个连续的单引号表示
SQL
中的单引号)
@database_name
=
N
'tempdb'
,
--
执行上述
SQL
所用的
DataBase
@server
=
N
''
,
@database_user_name
=
N
''
,
@subsystem
=
N
'TSQL'
,
--
执行类型为“
Transact-SQL
脚本”
@cmdexec_success_code
=
0
,
@flags
=
0
,
@retry_attempts
=
0
,
@retry_interval
=
1
,
@output_file_name
=
N
''
,
@on_success_step_id
=
0
,
@on_success_action
=
1
,
@on_fail_step_id
=
0
,
@on_fail_action
=
2
IF
(
@@ERROR
<>
0
OR
@ReturnCode
<>
0
)
GOTO
QuitWithRollback
--
新建调度
EXECUTE
@ReturnCode
=
msdb.dbo.sp_add_jobschedule
@job_id
=
@JobID
,
@name
=
N
'Start01'
,
--
调度名称
@enabled
=
1
,
@freq_type
=
64
--
“
64
”
表示
当
SQLServerAgent
服务启动时运行
IF
(
@@ERROR
<>
0
OR
@ReturnCode
<>
0
)
GOTO
QuitWithRollback
--
将新建的作业添加到本地数据库
EXECUTE
@ReturnCode
=
msdb.dbo.sp_add_jobserver
@job_id
=
@JobID
,
@server_name
=
N
'(local)'
IF
(
@@ERROR
<>
0
OR
@ReturnCode
<>
0
)
GOTO
QuitWithRollback
COMMIT
TRANSACTION
GOTO
EndSave
QuitWithRollback:
IF
(
@@TRANCOUNT
>
0
)
ROLLBACK
TRANSACTION
EndSave
:
/******
脚本结束
******/
4、
设置
Web.config
内容
打开
Web.config
→
找到
<
sessionState
>
节点内容
→
修改为以下内容即可:
<
sessionState
mode
="SQLServer"
sqlConnectionString
="data source=192.168.0.2; user id=
SessionStateUser; password=123456"
timeout
="20"
/>
注意事项:
a)
、
sqlConnectionString
中不能出现
initial catalog
选项
b)
、
SQL Server Agent
在此处的作用是清除数据库中已过期的
Session
c
)、你若跳过了第三步,则
user id
需要用
sa
进行登录
d
)、若
sqlConnectionString
为
“
data source=127.0.0.1;Trusted_Connection=yes
”,则使用本地计算机
ASPNET
(
Windows 2000
系统帐户)或
Network Service
(
Windows 2003
系统帐户)的身份登录数据库。要是数据库不允许上述用户登录,则报错;同样,即使上述帐户能成功登录,也要分配其
tempdb
的权限,理由是
Session
是保存在
tempdb
中的,若没有该
DataBase
的存取权限是行不滴。见下图:
寒羽枫(
cityhunter172
)
2006-05-14 00:01
完稿