• 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.
    
    ";
                message += "Action: " + action + "
    
    ";
                message += "Exception: " + e;
    
                log.WriteEntry(message);
            }
        }
    }
    

    未解决的问题

    • 统计在线人数,Session共享后如何来处理
    • 不能序列化的数据,如何处理

    其他相关链接

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

  • 相关阅读:
    Django ORM 进行查询操作和性能优化
    Python PIL 长文本换行,二维码,图片合成
    python 常用的资料链接
    人生苦短,我用Python
    windows下搭建Python virtualenvvirtualenvwrapper虚拟环境。
    Python 文件上传base64图片
    python实现中文转换url编码的方法
    同时装了Python3和Python2,怎么用pip?
    统计当天下单量
    Django ORM 级联删除
  • 原文地址:https://www.cnblogs.com/NoRoad/p/3434245.html
Copyright © 2020-2023  润新知