存储session状态在SQL 服务器的数据库中Storing Session State in a SQL Server Database)

Storing Session State in a SQL Server Database
Go to page: 1  2  3  Next  
http://www.developer.com/net/asp/article.php/3595766
 
HTTP 是一种无状态的协议。可以允许用户通过需求来保存状态信息。ASP.NET 提供了session的存储。Session变量在基于每用户的原理上被保存的。在经典的ASP中,你只能把你的session的变量保存在WEB服务器的内存之中。然而,在ASP.NET 2.0中,你可以把session状态保存作为你的每次的需求一样来定制。这篇文章将探究可升级的,可靠的session保存途径的一种――SQL Server
Session状态跟相关的问题
 
在经典的ASP中,通过默认得session状态被维持在WEB服务器的内存中,然后,这样的做法有两个问题:
  • 加重服务器负担,影响WEB站的可升级性
  • 不能在Web farm场景中有效的使用
Session 变量在每用户的原则上被创建。默认情况下,他们被维护在WEB 服务器的内存中。想象一下,一个网站有上千个(同时在线)用户。在WEB服务器中激活的Sessions数量将是非常之大。这意味着你正在储存太多的数据在WEB服务器的内存中。如果服务器的负载持续上涨,服务器的负载将达到饱和,然后会给你的应用程序的所有的拓展升级带来麻烦。
为了处理大家所提到的可拓展升级性的问题,(更好的)实现WEB FARM(技术)。一个WEB FARM 就是一个并联平行的服务器群。在这个群中的每台WEB服务器有你的网站的映射。你的网站的通信平等的分布在这些可用的服务器中,因而实现了负载的平等分配。保存session变量在WEB服务器中可能会牵制 WEB FARM的架构。假设这里有3WEB服务器- S1S2,和S3-平行的相连和对进来的请求进行服务。一个请求R1进来了这个群,负载平衡的架构逻辑决定了当S2,S3繁忙,S1空闲,可以去处理你的请求的时候。自然的,这个请求被前置到S1中去处理。现在,想象一下在处理的过程中,你保存了一个session变量在S1的内存中,到目前为止,都还好。过了一些时候,同一个用户给了另外的一个请求R2, R2需要被R1保存的那个session变量。然而,这次S1在处理另外的一些工作,而S2S3空闲。你可能会希望像前面的负载平衡逻辑规则那样,R2应该前置到S2或者S3(去处理)。可是,如果那样做的话,R2怎么去取访问存在WEB 服务器 S1中的session变量呢, 毕竟,他们是保存在完全不同的服务器 S1上。这就意味着R2 需要一直等待S1变得空闲事,才能够被处理。这就是,显然的,WEB FARM资源的不合理使用了。
 
ASP.NET 2.0 and Session Storage
ASP.NET 2.0 Session 存储
ASP.NET 2.0 allows you to store session variables at three distinct locations:
ASP.NET 2.0 允许你保存session变量在3个不同的地方
 
  1. WEB服务器的内存中(在处理过程中)
  2. 在专用的保存sesseion变量的机器中(状态服务器)
  3. SQL 服务器的数据库中
 
第一个模式是默认得。第二和第三模式经常称为“out-of-process”模式。因为session存储是独立于网站的。在本文中,所有的讨论都将限制在第三种模式。
 
保存session变量在SQL服务器中有以下的优点:
 
  • 可拓展性:如果你正在找一个高度可升级的选择来保存你的session变量的话,SQL服务器是一个选择。它比其它的选择更具有拓展升级的性能。Web farm 架构能够非常容易的访问session 变量因为它们存储在一个独立的数据库中。
  • 稳定性: 因为数据在数据库中是物理的持续的,这比其它任何一种都要稳定。即使服务器重启了,数据都还完好。
  • 安全性:SQL Server 比任何的内存中保存session或者专用的状态服务器选择都要来得安全。你可以很容易的通过配置SQL 服务器的安全设置来保护你的数据安全。
 
 
Session 状态模式可以通过web.config 文件的<sessionState>标记被配置.
 
注意:
·   Web farm 场景中,所有的WEBFARM中的服务器的 IIS metabase网站程序路径应该是同一路径
·   Session_End 事件不能因为任何异常模式而被使用
配置SQL 服务器来存储Session 状态
在你存储session状态在SQL服务器之前, 你需要去配置它. 这些配置可以通过一个叫 ASPNET_REGSQL.EXE 的命令行工具来实现. 你可以存储session状态在三个可能的地点.这些地点都是在SQL服务器之内的.
 
  • 临时存储: 在这种情况下, session 状态被存储在一个"临时数据库"SQL 服务器的数据库中. 这个工具创建了一个叫ASPState的数据库, 还添加了一些管理session的存储过程在里面. 这个工具还创建必需的表在临时数据库. 如果你重启了SQL 服务器,这些session数据将被删除.  
  • 持久存储: 这个工具创建了一个叫ASPState 的数据库, 还添加了一些管理session的存储过程在里面. Session 状态被储存在ASPState的数据库中.
 
  • 定制存储: session 和存储过程都被存储在一个定制的数据库中. 这个数据库的名字必须在配置文件中被指定.
 
 
 
以下的表列出了有关于session存储配置工具转换的不同命令:
 
Command line switch
Description
-S <server>
指定你想要用于存储session状态的数据库的IP地址或者名字
-U
指定被用来连接数据库的用户ID
-P
指定被用来连接数据库的密码
-E
指出你想要连接的服务器需要完整的安全策略
-ssadd
添加支持服务器模式的session状态
-ssremove
移除支持服务器模式的session状态
-sstype
Session状态支持的类型,一下是可以支持的类型:
t 代表临时存储
p
代表持久存储
c
代表定制储存
-d <database>
用于使用的数据库的名字如果要转换-sstype,就用命令”c”
Tables and Stored Procedures Created
表单和创建的存储过程
作为一个开发人员, 你可能从来无法对session状态数据库进行直接的影响. 然而, 当你运行ASPNET_REGSQL.EXE 工具, 你将会对表单跟数据库的创建会有一个很好的理解.
 
Figure 1:SQL数据库服务器中创建表单
Figure 2:在数据库服务器中创建存储过程
 

配置你的网站来存储Session 状态

一旦你配置你的SQL服务器来支持session状态存储,下一步就是配置你的网站了。web.config 的标记<sessionState>允许你指定session存储的信息。下列的表中列出了一些这个标记得重要属性:

属性

描述

mode

Mode属性可以使用一下的几个值:

Off:指示这个session状态关闭.
InProc:
指示这个session 将被存储在web服务器的内存中。这是默认的设置                                   StateServer:指示这个session将被储存在一个状态服务器中 SQLServer: 指示这个session将被储存在一个SQL服务器的数据库中.
Custom:
指示你将会有一个定制的session存储机制,这个机制使用了ASP.NET的提供的模式

sqlConnectionString

如果模式被设置为SQL服务器,你必须指定这个属性。这个属性指定了那个SQL服务器数据库的连接字符串。这个数据库的是用来进行状态的存储的。注意,如果你使用了临时的或者持久的存储选项时候,你不需要在连接字符串中指定数据库的名称(见上)

 

allowCustomSqlDatabase

如果你想去存储session状态在一个你自己的SQL服务器的数据库中的时候,你必须设置这个属性为“TRUE”。一旦这个属性被设置为true,你要在上面说描述的连接字符串中指定数据库的名称。

例子   

你可以开发一个简单的网站,设置它来存储一个sesseion状态在一个SQL服务器的数据库中,来示例你到目前为止以上所学的。

设置SQL服务器

打开Visual Studio.NET 2005命令提示器,使用一下命令

aspnet_regsql -ssadd -S .sqlexpress -E -sstype p

 

aspnet_regsql -ssadd -S .sqlexpress -E -sstype p

 

这里,你正在使用SQL Express 作为带着完整安全的数据库

Figure 3 展示了一个把带着session 状态类型的工具设置为"persistent"的例子。




Click here for a larger image.

Figure 3: 运行ASPNET_REGSQL.EXE工具    

创建和配置一个网站

现在,创建一个新的网站,修改web.config文件成下列的代码

<sessionState

mode="SQLServer"

sqlConnectionString="data source=.sqlexpress;

integrated security=true">

</sessionState>

这里,你添加了这个<sessionState>标记,设置它的模式属性为SQLServer。你还要指定sqlConnectionString属性,把它指向你的SQL SERVER

创建测试网站的WEB窗体

 

WEB站点中添加两个WEB窗体。这两个窗体分别叫page1.aspxpage2.aspx。第一个WEB窗体将显示一个产品列表来选择。被选择的产品被保存在一个DataSet中。然后通过保存这个DataSet 在一个session变量中来把它在请求中传递。第二个Web窗体简单的显示了来自DataSet中的被选择的产品。

通过一下的步骤来完成第一个Web 窗体:

  1. 拖拉一个GRIDVIEW控件和一个SQL Data Source控件在WEB FORM.
  2. 配置SQL Data Source, Northwind 数据库的Products 表中选择ProductID, ProductName, UnitPrice columns
  3. 通过设置他的DataSourceID属性到SQL Data Source控件的ID属性上来绑定GridViewSQL Data Source.
  4. GridViewsamrt标记上, 点击"Allow Selection" checkbox.
  5. 添加一个HyperLink 控件,设置NavigateUrl属性到Page2.aspx.

下列的标记是由上面的操作生成的(出去不必要的代码)

...

<asp:GridView ID="GridView1" runat="server"

              AllowPaging="True" AutoGenerateColumns="False"

              CellPadding="4" DataSourceID="SqlDataSource1"

              ForeColor="#333333" GridLines="None"

              Width="100%"

              OnSelectedIndexChanged="GridView1_SelectedIndexChanged"

              PageSize="5">

   <FooterStyle BackColor="#990000" Font-Bold="True"

                ForeColor="White" />

   <Columns>

      <asp:BoundField DataField="ProductName"

                      HeaderText="ProductName"

                      SortExpression="ProductName" />

      <asp:BoundField DataField="UnitPrice"

                      HeaderText="UnitPrice"

                      SortExpression="UnitPrice" />

      <asp:CommandField SelectText="Add to cart"

                        ShowSelectButton="True" />

   </Columns>

</asp:GridView>

...

<asp:HyperLink ID="HyperLink1" runat="server"

               NavigateUrl="~/Page2.aspx" Font-Bold="True"

               Font-Size="Large">Show my cart</asp:HyperLink>

...

<asp:SqlDataSource ID="SqlDataSource1" runat="server"

                   ConnectionString=

                   "<%$ ConnectionStrings:NorthwindConnectionString %>"

                   SelectCommand="SELECT [ProductName],

                   [UnitPrice] FROM [Products]

                   ORDER BY [ProductName]"></asp:SqlDataSource>

Now, add the following code to the SelectedIndexChanged event of the GridView:

protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)

{

   DataSet ds=null;

   if (Session["myds"] == null)

   {

      ds = new DataSet();

      DataTable dt = new DataTable();

      dt.Columns.Add(new DataColumn("ProductName"));

      dt.Columns.Add(new DataColumn("Qty", typeof(System.Int32)));

      ds.Tables.Add(dt);

      Session["myds"] = ds;

   }

   else

   {

      ds = (DataSet)Session["myds"];

   }

   DataRow row=ds.Tables[0].NewRow();

   row["productname"]=GridView1.Rows[GridView1.SelectedIndex].

      Cells[0].Text;

   row["Qty"]=1;

   ds.Tables[0].Rows.Add(row);

}

这里,你可以创建一个 DataSet   DataTable. FataTable 包含两个DataColumns: ProducyName Qty. 然后你存储一个session变量"myds".当用户选择一个产品的时候, 你可以创建一个新的DataRow, 分配产品的资料给它, 添加这个ROWDataTable. 用户的选择可以在跨多个请求中持续.

按一下的步骤创建第二张的Web form

  1. 拖拉一个GridViewWeb form.
  2. 添加两个绑定区域
  3. 设置第一个绑定区域的HeaderText属性成"Product Name". 同样的,设置DataField"Product Name".
  4. 设置第二个绑定区域的HeaderText属性成"Quantity". 同样的,设置DataField" Qty ".

 

下列的标记是由上面的操作生成的(除去不必要的代码)

 

 

...

<asp:GridView ID="GridView1" runat="server"

              AutoGenerateColumns="False" CellPadding="4"

              ForeColor="#333333" GridLines="None" Width="100%">

   <FooterStyle BackColor="#1C5E55" Font-Bold="True"

                ForeColor="White" />

   <Columns>

      <asp:BoundField DataField="productname"

                      HeaderText="Product Name" />

      <asp:BoundField DataField="qty"

                      HeaderText="Quantity" />

   </Columns>

</asp:GridView>

...

添加下列的代码到第二张Web Form Page_Load event handler

protected void Page_Load(object sender, EventArgs e)

{

   GridView1.DataSource=(DataSet)Session["myds"];

   GridView1.DataBind();

}

 

这里,你设置GridView控件的DataSource属性到你的储存在session上的DATASET.

然后你通过调用DataBind() 方法来绑定GridView.

运行WEB FORMS 的例子

为了测试你的WEB FORMS, 设置Page.aspx 作为你的起始页, 然后运行你的WEB SITE. 你应该看到如图4所展示的:

Figure 4: 运行Page1.aspx 的例子

 

 

通过”Add to cart”按钮选择一些产品. 这将会添加一些行在DataTable. 记得你正在存储你的DataSet在一个session变量之中. 然后,通过点击”Show my cart” 超链接导航到 Page.aspx . 5显示了带着前面所选的产品的Page.aspx.

Figure 5: Sample run of Page2.aspx

正如你所见的, Page2.aspx 正确的显示了你在前页所选的那些条目. 这显示了你的session 变量被真正的存储在了SQL服务器的数据库中,并被在第二页中找回. 还有, 注意你在无关储存模式的session中用了相同的存储调用值得标记.

储存Session状态在SQL服务器中的劣势

虽然存储session状态在SQL 服务器中可以使你的网站更容易拓展和更稳定. 但是这个技术有一下的几个劣势

 

  • 执行上: 在执行的几个项目中,一个基于SQL SERVERsession 存储可能是一个最慢地选择. 因为你的session变量是存储在物理的数据库中.它用了更多的时候去存储和读取数据库. 这会影响了你的网站的运行速度.
  • 花费: 因为你存储你的数据在数据库中, 你需要一个SQL数据库的执照, 这将给你的网站带来额外的开销.
  • 连续的数据: 这个方法要求你所有保存在session变量中的数据必须是连续的. 如果你想存储数据在一个session,这也许强制你去标记你自己的类作为[Serializable].

总结

rage options.

ASP.NET 2.0 可以允许你存储session状态到一个SQL服务器的数据库. ASPNET_REGSQL.EXE工具配置了数据库来支持这个特性. 更进一步, <sessionState>标记配置你的网站来支持这个模式. 存储一个session状态在一个SQL服务器中是一种更具拓展,安全性和稳定性的选择. 然后, 这种选择的运行相对于其他选择而言将会更慢.

下载代码,

You can download the code that accompanies the article here.

 

 

 

 

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭