介绍
由于针对于自定义Session存储方式比较少,所以整理了使用自定义Session的方式。用于构建自定义会话存储提供程序代码,而不是使用默认的 SessionStore 介绍
背景
本文使用的是mysql数据库作为存储session的媒介,其他的方式请自行测试
如何来做自定义session
使用的表格式,建表语句如下:
/****** 对象: Table Sessions 脚本日期: 2013/11/20 星期三 15:28:09 ******/ /****** 字段数据长度 = 4011 字节 ******/ DROP TABLE IF EXISTS `Sessions`; CREATE TABLE `Sessions`( `SessionID` varchar(50) NOT NULL DEFAULT '' COMMENT 'ID', `ApplicationName` varchar(255) NOT NULL DEFAULT '' COMMENT '应用程序名', `CreateTime` datetime NOT NULL DEFAULT '1900-01-01 00:00:00' COMMENT '创建时间', `ExpiresTime` datetime NOT NULL DEFAULT '1900-01-01 00:00:00' COMMENT '过期时间', `LockTime` datetime NOT NULL DEFAULT '1900-01-01 00:00:00' COMMENT '锁定时间', `LockID` int(4) NOT NULL DEFAULT 0 COMMENT '锁定ID', `TimeOut` int(4) NOT NULL DEFAULT 0 COMMENT '超时时间', `IsLocked` tinyint(4) unsigned NOT NULL DEFAULT 0 COMMENT '是否锁定(0:未锁定 / 1:锁定)', `SessionItems` varchar(3000) NOT NULL DEFAULT '' COMMENT 'Session内容', `Flags` int(4) NOT NULL DEFAULT 0 COMMENT '标记', `IsDelete` tinyint(4) unsigned NOT NULL DEFAULT 0 COMMENT '是否删除(0:未删除 / 1:删除)', `AddTime` datetime NOT NULL DEFAULT '1900-01-01 00:00:00' COMMENT '添加时间:数据添加Now()(now())', `ModifyTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '时间戳(CURRENT_TIMESTAMP)', PRIMARY KEY ( `SessionID` ), INDEX `IDX_Sessions_1` (`ApplicationName`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Session操作表:用于记录session使用数据';
我们定义一个CustomSessionStoreProvider,此类继承了SessionStateStore[roviderBase,里面里面的生成方式来进行处理,代码如下
namespace ShareSession
{
using System;
using System.Collections.Specialized;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Web;
using System.Web.Configuration;
using System.Web.SessionState;
using Better.Infrastructures.DBUtility;
using MySql.Data.MySqlClient;
/// <summary>
/// CustomSessionStoreProvider类
/// </summary>
public class CustomSessionStoreProvider
: SessionStateStoreProviderBase
{
/// <summary>
/// 事件源
/// </summary>
private const string EventSource = "ShareSession.CustomSessionStoreProvider";
/// <summary>
/// 事件日志名
/// </summary>
private const string EventLog = "Application";
/// <summary>
/// 连接.
/// </summary>
private readonly IDbConnection conn = new MySqlConnection(ConfigurationManager.ConnectionStrings["SessionsConn"].ConnectionString);
/// <summary>
/// Session状态对象
/// </summary>
private SessionStateSection configSection;
/// <summary>
/// 应用程序名
/// </summary>
private string applicationName = string.Empty;
/*
* If false, exceptions are thrown to the caller. If true,
* exceptions are written to the event log.
*/
/// <summary>
/// Initializes a new instance of the <see cref="CustomSessionStoreProvider"/> class.
/// </summary>
public CustomSessionStoreProvider()
{
this.WriteExceptionsToEventLog = false;
}
/// <summary>
/// 是否写入异常事件日志
/// </summary>
public bool WriteExceptionsToEventLog { get; set; }
/// <summary>
/// 应用程序名
/// </summary>
public string ApplicationName
{
get { return this.applicationName; }
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="name">名字</param>
/// <param name="config">配置集合</param>
public override void Initialize(string name, NameValueCollection config)
{
// Initialize values from web.config.
if (config == null)
{
throw new ArgumentNullException("config");
}
if (name.Length == 0)
{
name = "CustomSessionStateStore";
}
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "Custom Session State Store provider");
}
// Initialize the abstract base class.
base.Initialize(name, config);
// Initialize the ApplicationName property.
this.applicationName =
System.Web.Hosting.HostingEnvironment.ApplicationVirtualPath;
// Get <sessionState> configuration element.
var cfg =
WebConfigurationManager.OpenWebConfiguration(this.ApplicationName);
this.configSection =
(SessionStateSection)cfg.GetSection("system.web/sessionState");
// Initialize WriteExceptionsToEventLog
this.WriteExceptionsToEventLog = false;
if (config["writeExceptionsToEventLog"] != null)
{
if (config["writeExceptionsToEventLog"].ToUpper() == "TRUE")
{
this.WriteExceptionsToEventLog = true;
}
}
}
/// <summary>
/// 释放Session
/// </summary>
public override void Dispose()
{
}
/// <summary>
/// 设置session过期回调方法.
/// </summary>
/// <param name="expireCallback">
/// The expire callback.
/// </param>
/// <returns>
/// The <see cref="bool"/>.
/// </returns>
public override bool SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
{
return false;
}
/// <summary>
/// The set and release item exclusive.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
/// <param name="item">
/// The item.
/// </param>
/// <param name="lockId">
/// The lock id.
/// </param>
/// <param name="newItem">
/// The new item.
/// </param>
public override void SetAndReleaseItemExclusive(HttpContext context, string id, SessionStateStoreData item, object lockId, bool newItem)
{
// Serialize the SessionStateItemCollection as a string.
string sessItems = Serialize((SessionStateItemCollection)item.Items);
string tmpDeleteQuery;
try
{
string tmpQuery;
if (newItem)
{
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
// query to clear an existing expired session if it exists.
tmpDeleteQuery = @"UPDATE Sessions SET IsDelete = 1
WHERE SessionID = @session_id AND ApplicationName = @application_name AND ExpiresTime < now() ";
MySqlParameter[] deleParameters =
{
new MySqlParameter("@session_id", MySqlDbType.VarChar)
{
Value
=
id
},
new MySqlParameter("@application_name", MySqlDbType.VarChar)
{
Value
=
this
.ApplicationName
}
};
var row = MysqlHelper.ExecuteSql(null, this.conn, tmpDeleteQuery, deleParameters);
this.conn.Close();
if (row == 0)
{
// query to insert the new session item.
tmpQuery = @"INSERT INTO Sessions
(SessionID, ApplicationName, CreateTime, ExpiresTime,
LockTime, LockID, TimeOut, IsLocked, SessionItems, Flags, IsDelete, AddTime)
Values(@session_id, @app_name, now(),date_add(now(), interval @minute minute),
now(), @lock_id, @timeout, @locked, @session_items, @flags, 0, now())";
MySqlParameter[] insertParameters =
{
new MySqlParameter("@session_id", MySqlDbType.VarChar)
{
Value
=
id
},
new MySqlParameter("@app_name", MySqlDbType.VarChar)
{
Value
=
this
.ApplicationName
},
new MySqlParameter("@minute", MySqlDbType.Int32)
{
Value
=
item
.Timeout
},
new MySqlParameter("@lock_id", MySqlDbType.Int32)
{
Value
=
0
},
new MySqlParameter("@timeout", MySqlDbType.Int32)
{
Value
=
item
.Timeout
},
new MySqlParameter("@locked", MySqlDbType.Int16)
{
Value
=
0
},
new MySqlParameter("@session_items", MySqlDbType.VarChar) { Value = sessItems },
new MySqlParameter("@flags", MySqlDbType.Int32)
{
Value = 0
}
};
this.conn.Open();
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, insertParameters);
this.conn.Close();
}
else
{
tmpQuery =
@"UPDATE Sessions SET IsDelete = 0, CreateTime = now(), ExpiresTime = date_add(now(), interval @minute minute) , TimeOut = @TimeOut, SessionItems = @SessionItems WHERE SessionID=@SessionID";
MySqlParameter[] insertParameters =
{
new MySqlParameter("@minute", MySqlDbType.VarChar)
{
Value = item.Timeout
},
new MySqlParameter("@TimeOut", MySqlDbType.Int32)
{
Value
=
item
.Timeout
},
new MySqlParameter("@SessionItems", MySqlDbType.VarChar)
{
Value
=
sessItems
},
new MySqlParameter("@SessionID", MySqlDbType.VarChar)
{
Value
=
id
}
};
this.conn.Open();
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, insertParameters);
this.conn.Close();
}
}
else
{
// query to update the existing session item.
tmpQuery =
@"UPDATE Sessions SET ExpiresTime = date_add(now(), interval @minute minute), SessionItems = @sess_items, IsLocked = @locked WHERE SessionId = @sess_id AND ApplicationName = @app_name AND LockID = @lock_id limit 1";
MySqlParameter[] updateParameters =
{
new MySqlParameter("@minute", MySqlDbType.VarChar)
{
Value = item.Timeout
},
new MySqlParameter("@sess_items", MySqlDbType.VarChar)
{
Value
=
sessItems
},
new MySqlParameter("@locked", MySqlDbType.Int16)
{
Value = 0
},
new MySqlParameter("@sess_id", MySqlDbType.VarChar)
{
Value
=
id
},
new MySqlParameter("@app_name", MySqlDbType.VarChar)
{
Value
=
this
.ApplicationName
},
new MySqlParameter("@lock_id", MySqlDbType.Int32)
{
Value
=
lockId
}
};
this.conn.Open();
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, updateParameters);
this.conn.Close();
}
}
catch (Exception e)
{
if (this.WriteExceptionsToEventLog)
{
this.WriteToEventLog(e, "SetAndReleaseItemExclusive");
throw;
}
else
{
throw;
}
}
finally
{
this.conn.Close();
this.conn.Dispose();
}
}
/// <summary>
/// 初始化请求对象.
/// </summary>
/// <param name="context">
/// 请求文本内容.
/// </param>
public override void InitializeRequest(HttpContext context)
{
}
/// <summary>
/// 得到指定session数据.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
/// <param name="locked">
/// The locked.
/// </param>
/// <param name="lockAge">
/// The lock age.
/// </param>
/// <param name="lockId">
/// The lock id.
/// </param>
/// <param name="actions">
/// The actions.
/// </param>
/// <returns>
/// The <see cref="SessionStateStoreData"/>.
/// </returns>
public override SessionStateStoreData GetItem(
HttpContext context,
string id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actions)
{
return this.GetSessionStoreItem(
false,
context,
id,
out locked,
out lockAge,
out lockId,
out actions);
}
/// <summary>
/// The get item exclusive.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
/// <param name="locked">
/// The locked.
/// </param>
/// <param name="lockAge">
/// The lock age.
/// </param>
/// <param name="lockId">
/// The lock id.
/// </param>
/// <param name="actions">
/// The actions.
/// </param>
/// <returns>
/// The <see cref="SessionStateStoreData"/>.
/// </returns>
public override SessionStateStoreData GetItemExclusive(
HttpContext context,
string id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actions)
{
return this.GetSessionStoreItem(
false,
context,
id,
out locked,
out lockAge,
out lockId,
out actions);
}
/// <summary>
/// The release item exclusive.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
/// <param name="lockId">
/// The lock id.
/// </param>
public override void ReleaseItemExclusive(HttpContext context, string id, object lockId)
{
string tmpQuery = @"UPDATE Sessions SET IsLocked = 0, ExpiresTime = date_add(now(), interval @minute minute) WHERE SessionId = @sess_id AND ApplicationName = @app_name AND LockID = @lock_id Limit 1";
MySqlParameter[] parameters =
{
new MySqlParameter("@minute", MySqlDbType.VarChar) { Value = this.configSection.Timeout.Minutes },
new MySqlParameter("@sess_id", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName },
new MySqlParameter("@lock_id", MySqlDbType.Int32) { Value = lockId }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
try
{
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, parameters);
}
catch (Exception e)
{
if (this.WriteExceptionsToEventLog)
{
this.WriteToEventLog(e, "ReleaseItemExclusive");
throw;
}
else
{
throw;
}
}
finally
{
this.conn.Close();
}
}
/// <summary>
/// The remove item.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
/// <param name="lockId">
/// The lock id.
/// </param>
/// <param name="item">
/// The item.
/// </param>
public override void RemoveItem(HttpContext context, string id, object lockId, SessionStateStoreData item)
{
string tmpQuery = @"UPDATE Sessions SET IsDelete = 1 WHERE SessionId = @sess_id AND ApplicationName = @app_name AND LockId = @lock_id Limit 1";
tmpQuery = tmpQuery.Replace("@sess_id@", id);
tmpQuery = tmpQuery.Replace("@app_name@", this.ApplicationName);
tmpQuery = tmpQuery.Replace("@lock_id@", lockId.ToString());
MySqlParameter[] parameters =
{
new MySqlParameter("@sess_id", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName },
new MySqlParameter("@lock_id", MySqlDbType.Int32) { Value = lockId }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
try
{
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, parameters);
}
catch (Exception e)
{
if (this.WriteExceptionsToEventLog)
{
this.WriteToEventLog(e, "RemoveItem");
throw;
}
else
{
throw e;
}
}
finally
{
this.conn.Close();
}
}
/// <summary>
/// The reset item timeout.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
public override void ResetItemTimeout(HttpContext context, string id)
{
string tmpQuery = @"UPDATE Sessions SET ExpiresTime = date_add(now(), interval @minute minute) WHERE SessionId = @sess_id AND ApplicationName = @app_name Limit 1";
MySqlParameter[] parameters =
{
new MySqlParameter("@minute", MySqlDbType.VarChar) { Value = this.configSection.Timeout.Minutes },
new MySqlParameter("@sess_id", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
try
{
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, parameters);
}
catch (Exception e)
{
if (this.WriteExceptionsToEventLog)
{
this.WriteToEventLog(e, "ResetItemTimeout");
throw;
}
else
{
throw;
}
}
finally
{
this.conn.Close();
}
}
/// <summary>
/// The create new store data.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="timeout">
/// The timeout.
/// </param>
/// <returns>
/// The <see cref="SessionStateStoreData"/>.
/// </returns>
public override SessionStateStoreData CreateNewStoreData(HttpContext context, int timeout)
{
return new SessionStateStoreData(
new SessionStateItemCollection(),
SessionStateUtility.GetSessionStaticObjects(context),
timeout);
}
/// <summary>
/// The create uninitialized item.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
/// <param name="id">
/// The id.
/// </param>
/// <param name="timeout">
/// The timeout.
/// </param>
public override void CreateUninitializedItem(HttpContext context, string id, int timeout)
{
try
{
var tmpQuery =
@"UPDATE Sessions SET IsDelete = 0, CreateTime = now(), ExpiresTime = date_add(now(), interval @minute minute), TimeOut = @TimeOut, SessionItems = @SessionItems WHERE SessionID=@SessionID Limit 1";
MySqlParameter[] parameters =
{
new MySqlParameter("@minute", MySqlDbType.VarChar)
{
Value = timeout
},
new MySqlParameter("@TimeOut", MySqlDbType.Int32) { Value = timeout },
new MySqlParameter("@SessionItems", MySqlDbType.VarChar)
{
Value =
string
.Empty
},
new MySqlParameter("@SessionID", MySqlDbType.VarChar) { Value = id }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
var row = MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, parameters);
this.conn.Close();
if (row != 0)
{
return;
}
// query to insert the new session item.
tmpQuery = @"INSERT INTO Sessions
(SessionID, ApplicationName, CreateTime, ExpiresTime,
LockTime, LockID, TimeOut, IsLocked, SessionItems, Flags, IsDelete, AddTime)
Values(@session_id, @app_name, now(),date_add(now(), interval @minute minute),
now(), @lock_id, @timeout, @locked, @session_items, @flags, 0, now())";
MySqlParameter[] insertParameters =
{
new MySqlParameter("@session_id", MySqlDbType.VarChar)
{
Value
=
id
},
new MySqlParameter("@app_name", MySqlDbType.VarChar)
{
Value =
this
.ApplicationName
},
new MySqlParameter("@minute", MySqlDbType.VarChar)
{
Value = timeout
},
new MySqlParameter("@lock_id", MySqlDbType.Int32) { Value = 0 },
new MySqlParameter("@timeout", MySqlDbType.Int32)
{
Value =
timeout
},
new MySqlParameter("@locked", MySqlDbType.Int16) { Value = 0 },
new MySqlParameter("@session_items", MySqlDbType.VarChar)
{
Value
=
string
.Empty
},
new MySqlParameter("@flags", MySqlDbType.Int32) { Value = 0 }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, insertParameters);
}
catch (Exception e)
{
if (this.WriteExceptionsToEventLog)
{
this.WriteToEventLog(e, "ResetItemTimeout");
throw;
}
else
{
throw;
}
}
finally
{
this.conn.Close();
this.conn.Dispose();
}
}
/// <summary>
/// The end request.
/// </summary>
/// <param name="context">
/// The context.
/// </param>
public override void EndRequest(HttpContext context)
{
}
/// <summary>
/// 反序列化对象
/// </summary>
/// <param name="context">请求文本内容对象</param>
/// <param name="serializedItems">序列化项目</param>
/// <param name="timeout">超时时间</param>
/// <returns>返回构造好的Session储存对象</returns>
private static SessionStateStoreData Deserialize(HttpContext context, string serializedItems, int timeout)
{
MemoryStream ms =
new MemoryStream(Convert.FromBase64String(serializedItems));
SessionStateItemCollection sessionItems =
new SessionStateItemCollection();
if (ms.Length > 0)
{
BinaryReader reader = new BinaryReader(ms);
sessionItems = SessionStateItemCollection.Deserialize(reader);
}
return new SessionStateStoreData(
sessionItems,
SessionStateUtility.GetSessionStaticObjects(context),
timeout);
}
/// <summary>
/// 序列化
/// </summary>
/// <param name="items">需序列化的session对象</param>
/// <returns>返回序列化字符串</returns>
private static string Serialize(SessionStateItemCollection items)
{
MemoryStream ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);
if (items != null)
{
items.Serialize(writer);
}
writer.Close();
return Convert.ToBase64String(ms.ToArray());
}
/// <summary>
/// 得到session存储对象
/// </summary>
/// <param name="lockRecord">是否锁定记录</param>
/// <param name="context">请求对象文本</param>
/// <param name="id">唯一id</param>
/// <param name="locked">返回是否锁定</param>
/// <param name="lockAge">锁定时长</param>
/// <param name="lockId">锁定Id</param>
/// <param name="actionFlags">触发标记</param>
/// <returns>返回Session状态存储对象数据</returns>
private SessionStateStoreData GetSessionStoreItem(
bool lockRecord,
HttpContext context,
string id,
out bool locked,
out TimeSpan lockAge,
out object lockId,
out SessionStateActions actionFlags)
{
// Initial values for return value and out parameters.
SessionStateStoreData item = null;
lockAge = TimeSpan.Zero;
lockId = null;
locked = false;
actionFlags = 0;
// DateTime to check if current session item is expired.
DateTime expires;
// String to hold serialized SessionStateItemCollection.
string serializedItems = string.Empty;
// True if a record is found in the database.
bool foundRecord = false;
// True if the returned session item is expired and needs to be deleted.
bool deleteData = false;
// Timeout value from the data store.
int timeout = 0;
try
{
string tmpQuery;
// lockRecord is true when called from GetItemExclusive and
// false when called from GetItem.
// Obtain a lock if possible. Ignore the record if it is expired.
if (lockRecord)
{
tmpQuery = @"UPDATE Sessions SET IsLocked = @Islocked, LockTime = now()
WHERE SessionID = @sessionid AND ApplicationName = @app_name AND ExpiresTime > now() AND IsDelete = 0";
MySqlParameter[] parameters =
{
new MySqlParameter("@Islocked", MySqlDbType.Int16) { Value = 1 },
new MySqlParameter("@sessionid", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
locked = MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, parameters) == 0;
this.conn.Close();
}
// Retrieve the current session item information.
tmpQuery = @"SELECT ExpiresTime, SessionItems, LockID, LockTime, Flags, TimeOut FROM Sessions WHERE SessionID = @sessionid AND ApplicationName = @app_name AND IsDelete = 0";
MySqlParameter[] seleParameters =
{
new MySqlParameter("@sessionid", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
// Retrieve session item data from the data source.
using (var reader = MysqlHelper.ExecuteReader(null, this.conn, tmpQuery, seleParameters))
{
if (reader.HasRows)
{
while (reader.Read())
{
expires = reader.IsDBNull(reader.GetOrdinal("ExpiresTime")) ? DateTime.Parse("1900-1-1") : reader.GetDateTime(reader.GetOrdinal("ExpiresTime"));
if (expires < DateTime.Now)
{
// The record was expired. Mark it as not locked.
locked = false;
// The session was expired. Mark the data for deletion.
deleteData = true;
}
else
{
foundRecord = true;
}
serializedItems = reader.IsDBNull(reader.GetOrdinal("SessionItems")) ? string.Empty : reader.GetString(reader.GetOrdinal("SessionItems"));
lockId = reader.IsDBNull(reader.GetOrdinal("LockID")) ? 0 : reader.GetInt32(reader.GetOrdinal("LockID"));
lockAge = DateTime.Now.Subtract(reader.IsDBNull(reader.GetOrdinal("LockTime")) ? DateTime.Parse("1900-1-1") : reader.GetDateTime(reader.GetOrdinal("LockTime")));
actionFlags = (SessionStateActions)(reader.IsDBNull(reader.GetOrdinal("Flags")) ? 0 : reader.GetInt32(reader.GetOrdinal("Flags")));
timeout = reader.IsDBNull(reader.GetOrdinal("TimeOut")) ? 0 : reader.GetInt32(reader.GetOrdinal("TimeOut"));
}
}
}
this.conn.Close();
// If the returned session item is expired,
// delete the record from the data source.
if (deleteData)
{
tmpQuery = @" UPDATE Sessions SET IsDelete = 1 WHERE SessionID = @sess_id AND ApplicationName = @app_name AND IsDelete = 0 Limit 1";
MySqlParameter[] deleParameters =
{
new MySqlParameter("@sessionid", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, deleParameters);
this.conn.Close();
}
// The record was not found. Ensure that locked is false.
if (!foundRecord)
{
locked = false;
}
// If the record was found and you obtained a lock, then set
// the lockId, clear the actionFlags,
// and create the SessionStateStoreItem to return.
if (foundRecord && !locked)
{
lockId = (int)lockId + 1;
tmpQuery = @" UPDATE Sessions SET LockId = @lock_id, Flags = @flags WHERE SessionID = @sess_id AND ApplicationName = @app_name Limit 1";
MySqlParameter[] updateParameters =
{
new MySqlParameter("@lock_id", MySqlDbType.Int32) { Value = lockId },
new MySqlParameter("@flags", MySqlDbType.Int32) { Value = 0 },
new MySqlParameter("@sess_id", MySqlDbType.VarChar) { Value = id },
new MySqlParameter("@app_name", MySqlDbType.VarChar) { Value = this.ApplicationName }
};
if (this.conn.State != ConnectionState.Open)
{
this.conn.Open();
}
MysqlHelper.ExecuteSql(null, this.conn, tmpQuery, updateParameters);
this.conn.Close();
// If the actionFlags parameter is not InitializeItem,
// deserialize the stored SessionStateItemCollection.
if (actionFlags == SessionStateActions.InitializeItem)
{
item = this.CreateNewStoreData(context, this.configSection.Timeout.Minutes);
}
else
{
item = Deserialize(context, serializedItems, timeout);
}
}
}
catch (Exception e)
{
if (this.WriteExceptionsToEventLog)
{
this.WriteToEventLog(e, "GetSessionStoreItem");
throw;
}
else
{
throw;
}
}
finally
{
this.conn.Close();
this.conn.Dispose();
}
return item;
}
/// <summary>
/// 写入事件日志
/// </summary>
/// <param name="e">异常对象</param>
/// <param name="action">触发点</param>
private void WriteToEventLog(Exception e, string action)
{
EventLog log = new EventLog { Source = EventSource, Log = EventLog };
string message =
"An exception occurred communicating with the data source.\n\n";
message += "Action: " + action + "\n\n";
message += "Exception: " + e;
log.WriteEntry(message);
}
}
}
未解决的问题
- 统计在线人数,Session共享后如何来处理
- 不能序列化的数据,如何处理
其他相关链接
http://msdn.microsoft.com/en-us/library/ms178589(v=vs.100).aspx