65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 ASP.NET 的 MySQL 会话状态提供程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.48/5 (9投票s)

2013年8月7日

CPOL

4分钟阅读

viewsIcon

37860

MySQL Connector/Net ASP.NET 会话状态提供程序的设置和配置

Content

  • 介绍 
  • 手动设置 MySQL 会话状态提供程序
  • 示例代码 
  • 来自官方 MySQL Dot Net Connector 的代码 
  • 问答 


引言

什么是会话状态?  

ASP.NET 会话状态使您能够在用户浏览 Web 应用程序中的 ASP.NET 页面时存储和检索用户的值。HTTP 是一个无状态协议。这意味着 Web 服务器将页面收到的每个 HTTP 请求视为独立请求。服务器不保留之前请求期间使用的变量值的任何知识。ASP.NET 会话状态在有限的时间窗口内将同一浏览器发出的请求识别为一个会话,并提供一种在会话期间持久化变量值的方法。默认情况下,所有 ASP.NET 应用程序都启用了 ASP.NET 会话状态。(摘自 ASP.NET 会话状态概述


默认情况下,ASP.NET 会话状态存储在计算机的物理内存中。如果大量客户端同时访问网站,物理内存将完全耗尽,显然是不够的。禁用会话状态的使用可以解决此问题。解决此问题的另一种方法是将会话状态的数据存储在数据库中。

本文将介绍如何使用 MySQL 作为会话状态存储提供程序,以及如何将其配置为与 ASP.NET 一起使用。

手动设置 MySQL 会话状态提供程序  

首先,我们必须创建一个类并继承 System.Web.SessionState.SessionStateStoreProviderBase,然后实现所有抽象和虚拟方法。

示例: 

using System;
using System.Web;
using System.Web.Configuration;
using System.Configuration;
using System.Configuration.Provider;
using System.Collections.Specialized;
using System.Web.SessionState;
using System.Data;
using System.Diagnostics;
using System.IO;
using MySql.Data.MySqlClient;

namespace MyWebsite
{
    public class MySessionStateConfig : SessionStateStoreProviderBase
    {
        public override void Initialize(string name, NameValueCollection config)
        {
            base.Initialize(name, config);
        }

        public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
        {
            throw new NotImplementedException();
        }

        public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
        {
            throw new NotImplementedException();
        }

        public override void Dispose()
        {
            throw new NotImplementedException();
        }

        public override void EndRequest(HttpContext context)
        {
            throw new NotImplementedException();
        }

        public override SessionStateStoreData GetItem(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            throw new NotImplementedException();
        }

        public override SessionStateStoreData GetItemExclusive(HttpContext context, string id, out bool locked, out TimeSpan lockAge, out object lockId, out SessionStateActions actions)
        {
            throw new NotImplementedException();
        }

        public override void InitializeRequest(HttpContext context)
        {
            throw new NotImplementedException();
        }

        public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
        {
            throw new NotImplementedException();
        }

        public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
        {
            throw new NotImplementedException();
        }

        public override void ResetItemTimeout(HttpContext context, string id)
        {
            throw new NotImplementedException();
        }

        public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
        {
            throw new NotImplementedException();
        }

        public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
        {
            throw new NotImplementedException();
        }
    }
}

然后,我们需要告诉 ASP.NET 使用我们定义的引擎(该类)来处理会话状态。这可以通过修改 Web.config 来完成。 

<configuration>
  <system.web>
    <sessionState cookieless="false" regenerateExpiredSessionId="true" mode="Custom" customProvider="MyCustomMadeSessionProvider">
      <providers>
        <add name="MyCustomMadeSessionProvider" 
		type="MyWebsite.MySessionStateConfig" 
		applicationName="/mywebapp" 
		description="my custom state provider" 
		writeExceptionsToEventLog="False"
		autogenerateschema="True"
		enableExpireCallback="False" />
      </providers>
    </sessionState>
  </system.web>
</configuration> 

我们在 Web.config 中的这一行将我们定义的引擎定向到我们的类

type="<namespace>.<class>.<class>...."

(在上面的示例中就是这样): 

type="MyWebsite.MySessionStateConfig"

接下来,我们需要做的是为创建类中的方法编写逻辑代码。 

示例:  

创建新会话状态时会调用此方法: 

public abstract void CreateUninitializedItem(HttpContext context, string id, int timeout); 

这是此方法可能被处理方式的示例

public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
    try
    {
        using (MySqlConnection conn = new MySqlConnection(connectionString))
        {
            using (MySqlCommand cmd = new MySqlCommand())
            {
                conn.Open();
                cmd.Connection = conn;

                cmd.CommandText = @"INSERT INTO sessions 
                (SessionId, ApplicationName, Created, Expires, LockDate, 
                LockId, Timeout, Locked, SessionItems, Flags)
                Values(@SessionId, @ApplicationName, @Created, @Expires, 
                @LockDate, @LockId, @Timeout, @Locked, @SessionItems, @Flags)";

                cmd.Parameters.Add("@SessionId", MySqlDbType.VarChar, 80).Value = id;
                cmd.Parameters.Add("@ApplicationName", MySqlDbType.VarChar, 255).Value = ApplicationName;
                cmd.Parameters.Add("@Created", MySqlDbType.DateTime).Value = DateTime.Now;
                cmd.Parameters.Add("@Expires", MySqlDbType.DateTime).Value = DateTime.Now.AddMinutes((Double)timeout);
                cmd.Parameters.Add("@LockDate", MySqlDbType.DateTime).Value = DateTime.Now;
                cmd.Parameters.Add("@LockId", MySqlDbType.Int32).Value = 0;
                cmd.Parameters.Add("@Timeout", MySqlDbType.Int32).Value = timeout;
                cmd.Parameters.Add("@Locked", MySqlDbType.Int32).Value = 0;
                cmd.Parameters.Add("@SessionItems", MySqlDbType.VarChar, 0).Value = "";
                cmd.Parameters.Add("@Flags", MySqlDbType.Int32).Value = 1;

                cmd.ExecuteNonQuery();
                conn.Close();
            }
        }
    }
    catch (MySqlException e)
    {
        if (WriteExceptionsToEventLog)
        {
            WriteToEventLog(e, "CreateUninitializedItem");
            throw new ProviderException(exceptionMessage);
        }
        else
            throw e;
    } 
}

有关 SessionStateStoreProviderBase 的类成员和方法的完整列表,以及有关方法调用时间和作用的说明,您可以参考

               >>  MSDN 官方文档 - SessionStateStoreProviderBase 类  

存储会话状态数据的数据库表结构没有固定。您可以定义自己的表结构。下面是一个表结构示例

 CREATE TABLE `sessions` (
  `SessionId` varchar(80) NOT NULL,
  `ApplicationName` varchar(255) NOT NULL,
  `Created` datetime NOT NULL,
  `Expires` datetime NOT NULL,
  `LockDate` datetime NOT NULL,
  `LockId` int(10) unsigned NOT NULL,
  `Timeout` int(10) unsigned NOT NULL,
  `Locked` smallint(1) unsigned NOT NULL,
  `SessionItems` longtext NOT NULL,
  `Flags` int(10) unsigned NOT NULL,
  PRIMARY KEY (`SessionId`,`ApplicationName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

示例代码 

访问数据库会话状态存储提供程序的示例代码 :

数据库、表、Web.config (设置): http://msdn.microsoft.com/en-us/library/ms178588(v=vs.100).aspx

SessionStateStoreProviderBase 类: http://msdn.microsoft.com/en-us/library/ms178589(v=vs.100).aspx 

MySQL 会话状态存储提供程序的示例代码 

2007 年,一位名叫 Harry Kimpel 的开发人员通过修改上述 MSDN 中的 Access 数据库代码,创建了一个类来处理 MySQL 中的会话状态。他写了一篇文章并在 codeproject.com 上分享了。

               >> 适用于 MySQL 的 ASP.NET 会话状态存储提供程序 

来自官方 MySQL Dot Net Connector 的代码 

现在,好消息是,从 MySQL Dot Net Connector 版本 6.1(2009 年 9 月,阅读更多)开始,**MySQL Connector/Net** 已包含/编写了类 - MySql.Web.SessionState.MySqlSessionStateStore

表结构也将自动创建。 

因此,我们无需手动编写自己的类来处理 MySQL 中的会话状态。现在我们要做的就是配置 Web.config 以告诉我们的 ASP.NET 使用 MySql.Web.SessionState.MySqlSessionStateStore 来处理会话状态。将 MySql.Web.dll(或您已安装连接器的全局程序集缓存中的 MySql.Web)的引用添加到项目中。 

修改 Web.config 

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <remove name="LocalMySqlServer" />
    <add name="LocalMySqlServer" connectionString="server=localhost;user=root;pwd=1234;database=mydatabase;" providerName="MySql.Data.MySqlClient" />
  </connectionStrings>
  <system.web>
    <sessionState cookieless="false" 
           regenerateExpiredSessionId="true" 
           mode="Custom" 
           customProvider="MySqlSessionStateProvider">
      <providers>
        <add name="MySqlSessionStateProvider" 
           type="MySql.Web.SessionState.MySqlSessionStateStore, MySql.Web, Version=6.6.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" 
           applicationName="/mywebapp" 
           description="MySQL Session State" 
           connectionStringName="LocalMySqlServer" 
           writeExceptionsToEventLog="False" 
           autogenerateschema="True" 
           enableExpireCallback="False" />
      </providers>
    </sessionState>
  </system.web>
</configuration>   

自动 Web.config 配置

是的,还有另一个好消息,MySQL Connector/NET 提供了一个名为 MySQL Website Configuration Tool 的工具来自动执行 Web.config 的配置。此工具将在 MySQL Connector/NET 与 Visual Studio 集成后可用。 

下载: MySQL Connector/NET。  

如果您在 Visual Studio 的解决方案资源管理器中看不到 MySQL Website Configuration Tool 的图标,可以尝试此操作:如何恢复 VS 2010 中的 MySQL Website Configuration Tool 图标

只需输入所有必需的信息,该工具将修改 Web.config 并写入所有必要的内容,以告知 ASP.NET 在 MySQL 中处理会话状态。  

 

MySQL Website Configuration Tool 的教程: https://dev.mysqlserver.cn/doc/refman/5.7/en/connector-net-website-config.html 

默认情况下,MySql.Web.SessionState.MySqlSessionStateStore 从 Web.config 获取连接字符串。此行为可以修改。出于某种原因,您可能不想将连接字符串存储在 Web.config 中。创建一个类(例如:MySession.MyModifiedSessionEngine),继承 MySql.Web.SessionState.MySqlSessionStateStore 并重写 Initialize 方法。 

public override void Initialize(string name, NameValueCollection config) 

默认连接字符串在 Initialize() 中定义如下: 

.... 
// Initialize connection.
connectionStringSettings = ConfigurationManager.ConnectionStrings[config["connectionStringName"]];
if (connectionStringSettings == null || connectionStringSettings.ConnectionString.Trim() == "")
    throw new HttpException("Connection string can not be blank");
connectionString = connectionStringSettings.ConnectionString; 
.... 

应用您自己的方式来获取连接字符串

 .... 
// Initialize connection.
connectionString = SomeMethodToGetConnectionString();
....  

修改 Web.config 以使用您的新会话状态引擎:(连接字符串已被删除,因为不再需要)

<?xml version="1.0"?>
<configuration>
  <system.web>
    <sessionState cookieless="false" 
           regenerateExpiredSessionId="true" 
           mode="Custom" 
           customProvider="MySqlSessionStateProvider">
      <providers>
        <add name="MySqlSessionStateProvider" 
           type="MySession.MyModifiedSessionEngine" 
           applicationName="/mywebapp" 
           description="MySQL Session State" 
           connectionStringName="LocalMySqlServer" 
           writeExceptionsToEventLog="False" 
           autogenerateschema="True" 
           enableExpireCallback="False" />
      </providers>
    </sessionState>
  </system.web>
</configuration>   

问答   

我可以在 代码后台 而不是 Web.config 中配置会话状态的设置吗? 

嗯,据我所知(我可能错了),根据此文档:  SessionStateSection 类 (MSDN),会话状态设置只能在 Web.config 中更改,并且在代码后台是**只读**的。 

 

我能获取 MySql.Web.SessionState.MySqlSessionStateStore 的源代码吗? 

是的,它是开源的。您可以在此处下载: https://dev.mysqlserver.cn/downloads/connector/net 

将“平台”更改为“源代码”。 

 

文章结束。编码愉快。 

© . All rights reserved.