介绍

由于针对于自定义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

Asp.Net 自定义储存Session方式的更多相关文章

  1. ASP.NET 使用mode=”InProc”方式保存Session老是丢失,无奈改成StateServer 模式。

    http://blog.csdn.net/fox123871/article/details/8165431 session是工作在你的应用程序进程中的.asp.net进程.iis往往会在20分钟之后 ...

  2. ASP.NET WebApi 基于分布式Session方式实现Token签名认证

    一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...

  3. ASP.NET WebApi 基于分布式Session方式实现Token签名认证(发布版)

    一.课程介绍 明人不说暗话,跟着阿笨一起学玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NETWebSer ...

  4. 连表查询都用Left Join吧 以Windows服务方式运行.NET Core程序 HTTP和HTTPS的区别 ASP.NET SignalR介绍 asp.net—WebApi跨域 asp.net—自定义轻量级ORM C#之23中设计模式

    连表查询都用Left Join吧   最近看同事的代码,SQL连表查询的时候很多时候用的是Inner Join,而我觉得对我们的业务而言,99.9%都应该使用Left Join(还有0.1%我不知道在 ...

  5. ASP.NET Core自定义中间件的方式

    ASP.NET Core应用本质上,其实就是由若干个中间件构建成的请求处理管道.管道相当于一个故事的框架,而中间件就相当于故事中的某些情节.同一个故事框架采用不同的情节拼凑,最终会体现出不同风格的故事 ...

  6. ASP.NET中的Session怎么正确使用

    Session对象用于存储从一个用户开始访问某个特定的aspx的页面起,到用户离开为止,特定的用户会话所需要的信息.用户在应用程序的页面切换时,Session对象的变量不会被清除. 对于一个Web应用 ...

  7. ASP.NET中的Session怎么正确使用[转]

    Session对象用于存储从一个用户开始访问某个特定的aspx的页面起,到用户离开为止,特定的用户会话所需要的信息.用户在应用程序的页面切换时,Session对象的变量不会被清除. 对于一个Web应用 ...

  8. 【译文】漫谈ASP.NET中的Session

    最近这两天被一个Web Farm环境下的Session处理问题虐得很痛苦,网上到处找解决方案,在无意中翻看到这篇文章,感觉很不错,顺手查了一下,貌似没有现成的译文,于是一咬牙一跺脚把这篇文章翻译出来了 ...

  9. ASP.NET 中的 Session 怎么正确使用

    Session对象用于存储从一个用户开始访问某个特定的aspx的页面起,到用户离开为止,特定的用户会话所需要的信息.用户在应用程序的页面切换时,Session对象的变量不会被清除. 对于一个Web应用 ...

随机推荐

  1. 关于C语言函数调用压栈和返回值问题的疑惑

    按照C编译器的约定调用函数时压栈的顺序是从右向左,并且返回值是保存在eax寄存器当中.这个命题本该是成立的,下面用一个小程序来反汇编观察执行过程: #include<stdio.h> in ...

  2. iOS Swift-HelloWord

    iOS Swift-HelloWord 按部就班选择Swif开发语言,输出HelloWord. override func viewDidLoad() { super.viewDidLoad() pr ...

  3. 拯救你的文档 – 【DevOps敏捷开发动手实验】开源文档发布

    今天上海的天气真是不错,风和日丽.再次来到微软上海紫竹研发中心,心情很是愉快,喜欢这里的大草坪,喜欢这里的工程气氛,更喜欢今天来陪我的小伙伴们. 这次动手实验培训与以往最大的不同就是采用了开源文档的方 ...

  4. TeamCity实战(1):准备工作

    环境: Windows Server 2008 R2 SP1(不会再有SP2,参考这里:http://www.techspot.com/news/50599-microsoft-wont-releas ...

  5. Openstack api 学习文档 & restclient使用文档

    Openstack api 学习文档 & restclient使用文档 转载请注明http://www.cnblogs.com/juandx/p/4943409.html 这篇文档总结一下我初 ...

  6. Linux mysql 5.6: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

    案例环境: 操作系统 :Red Hat Enterprise Linux Server release 5.7 (Tikanga) 64 bit 数据库版本 : Mysql 5.6.19 64 bit ...

  7. CRLF line terminators导致shell脚本报错:command not found

    Linux和Windows文本文件的行结束标志不同.在Linux中,文本文件用"/n"表示回车换行,而Windows用"/r/n"表示回车换行.有时候在Wind ...

  8. delete语句跑了3个小时分析以及关于并行的一些知识

    =====================START==================================== 闲来无事,看了下数据库跑的long running sql, SQL> ...

  9. 《java JDK7 学习笔记》之对象封装

    1.构造函数实现对象初始化流程的封装.方法封装了操作对象的流程.java中还可以使用private封装对象私有数据成员.封装的目的主要就是隐藏对象细节,将对象当做黑箱子进行操作. 2.在java命名规 ...

  10. 【转】hive导入数据出现NULL

    在把hdfs上数据迁移到hive中的表时,若出现数据位NULL,是因为没有指定列分隔符. 由于hive默认的分隔符是/u0001(Ctrl+A),为了平滑迁移,需要在创建表格时指定数据的分割符号,语法 ...