Asp.Net 自定义储存Session方式

介绍

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

转载于:https://www.cnblogs.com/NoRoad/p/3434245.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值