使用 ASP.NET 的 MySQL 会话状态提供程序
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
将“平台”更改为“源代码”。
文章结束。编码愉快。