湘水渔叟 發表於 2016-12-6 01:01:00

Asp.net 实现Session分布式储存(Redis,Mongodb,Mysql等) sessionState Custom

<p>  对于asp.net 程序员来说,Session的存储方式有InProc、StateServer、SQLServer和Custom,但是Custom确很少有人提及。但Custom确实最好用,目前最实用和最灵活一种方式,因为Custom可以实现各种情况的Session存储,特别对于大型网站尤为重要,解决Session丢失和Session效率的最佳实现方式,也是实现单点登录的最佳途径。 对于InProc、StateServer和SQLServer各自优缺点,网上一大堆,这里就不做详解。</p>
<p>&nbsp;</p>
<h1>重要的两点</h1>
<p>&nbsp;1、首先是关于Session存储,Session的存储并不是我们想象的,当设置Session时立即往数据容器里插入或者修改数据,当获取Session的值时就是立即去数据容器里获取值,这种理解是错误的(我之前就是这样理解的)。后来想想完全没必要这样操作,而且会大大影响效率。Asp.net的Session实现方式是每次请求前获取数据,当请求逻辑代码结束的时候在设置Session的值,所以说Session对数据容器的修改<strong>简单的意义</strong>只有两次,这个可能就要牵扯到管道流了。</p>
<p>2、第二个就是关于Asp.net网站异步的问题,<strong>当我们不设置Session的状态为只读时,我们每个用户的请求其实都是同步的,也就说每个用户请求网站同时只能有一个请求响应。</strong>理解这个就可以理解后面实现方法中需要锁的概念了。</p>
<p>&nbsp;</p>
<h2>SessionStateStoreProviderBase</h2>
<p>  SessionStateStoreProviderBase是asp.net框架为我们提供的一个用来存储Session提供程序所需的成员(就是实现这个类),我们知道的InProc、SQLServer、StateServer都是实现了这个抽象类。继承这个类需要有多个抽象方法需要实现。关于这多个方法没必要每个都实现,我们只关注我们需要实现的即可。说简单点就是对Session数据的增删改查(CRUD)。关于SessionStateStoreProviderBase的详情可以参考https://msdn.microsoft.com/zh-cn/library/system.web.sessionstate.sessionstatestoreproviderbase(v=vs.100).aspx</p>
<p>&nbsp;</p>
<table summary="table">
<tbody>
<tr><th scope="col">
<p>成员</p>
</th><th scope="col">
<p>说明</p>
</th></tr>
<tr>
<td data-th="
成员
                ">
<p>InitializeRequest&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例作为输入,并执行会话状态存储提供程序必需的所有初始化操作。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>EndRequest方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例作为输入,并执行会话状态存储提供程序必需的所有清理操作。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>Dispose&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>释放会话状态存储提供程序不再使用的所有资源。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>GetItemExclusive&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例和当前请求的&nbsp;SessionID&nbsp;值作为输入。从会话数据存储区中检索会话的值和信息,并在请求持续期间锁定数据存储区中的会话项数据。GetItemExclusive&nbsp;方法设置几个输出参数值,这些参数值将数据存储区中当前会话状态项的状态通知给执行调用的&nbsp;SessionStateModule。</p>
<p>如果数据存储区中未找到任何会话项数据,则&nbsp;GetItemExclusive&nbsp;方法将&nbsp;<span class="parameter">locked&nbsp;输出参数设置为&nbsp;<span class="input">false,并返回&nbsp;<span class="input">null。这将导致SessionStateModule&nbsp;调用&nbsp;CreateNewStoreData&nbsp;方法来为请求创建一个新的&nbsp;SessionStateStoreData&nbsp;对象。</span></span></span></p>
<p>如果在数据存储区中找到会话项数据但该数据已锁定,则&nbsp;GetItemExclusive&nbsp;方法将&nbsp;<span class="parameter">locked&nbsp;输出参数设置为&nbsp;<span class="input">true,将&nbsp;<span class="parameter">lockAge输出参数设置为当前日期和时间与该项锁定日期和时间的差,将&nbsp;<span class="parameter">lockId&nbsp;输出参数设置为从数据存储区中检索的锁定标识符,并返回&nbsp;<span class="input">null。这将导致&nbsp;SessionStateModule&nbsp;隔半秒后再次调用&nbsp;GetItemExclusive&nbsp;方法,以尝试检索会话项信息和获取对数据的锁定。如果&nbsp;<span class="parameter">lockAge&nbsp;输出参数的设置值超过&nbsp;ExecutionTimeout&nbsp;值,SessionStateModule&nbsp;将调用&nbsp;ReleaseItemExclusive&nbsp;方法以清除对会话项数据的锁定,然后再次调用&nbsp;GetItemExclusive&nbsp;方法。</span></span></span></span></span></span></p>
<p>如果&nbsp;<span class="input">regenerateExpiredSessionId&nbsp;属性设置为&nbsp;<span class="input">true,则&nbsp;<span class="parameter">actionFlags&nbsp;参数用于其&nbsp;Cookieless&nbsp;属性为&nbsp;<span class="input">true&nbsp;的会话。<span class="parameter">actionFlags&nbsp;值设置为&nbsp;InitializeItem&nbsp;(1) 则指示会话数据存储区中的项是需要初始化的新会话。通过调用CreateUninitializedItem&nbsp;方法可以创建会话数据存储区中未初始化的项。如果会话数据存储区中的项已经初始化,则<span class="parameter">actionFlags&nbsp;参数设置为零。</span></span></span></span></span></span></p>
<p>如果提供程序支持无 Cookie 会话,请将&nbsp;<span class="parameter">actionFlags&nbsp;输出参数设置为当前项从会话数据存储区中返回的值。如果被请求的会话存储项的&nbsp;<span class="parameter">actionFlags&nbsp;参数值等于&nbsp;InitializeItem&nbsp;枚举值 (1),则&nbsp;GetItemExclusive&nbsp;方法在设置&nbsp;<span class="parameter">actionFlags&nbsp;<span class="code">out&nbsp;参数之后应将数据存储区中的值设置为零。</span></span></span></span></p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>GetItem&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>除了不尝试锁定数据存储区中的会话项以外,此方法与&nbsp;GetItemExclusive&nbsp;方法执行的操作相同。GetItem&nbsp;方法在EnableSessionState&nbsp;属性设置为&nbsp;<span class="input">ReadOnly&nbsp;时调用。</span></p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>SetAndReleaseItemExclusive&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例、当前请求的&nbsp;SessionID&nbsp;值、包含要存储的当前会话值的&nbsp;SessionStateStoreData&nbsp;对象、当前请求的锁定标识符以及指示要存储的数据是属于新会话还是现有会话的值作为输入。</p>
<p>如果&nbsp;<span class="parameter">newItem&nbsp;参数为&nbsp;<span class="input">true,则&nbsp;SetAndReleaseItemExclusive&nbsp;方法使用提供的值将一个新项插入到数据存储区中。否则,数据存储区中的现有项使用提供的值进行更新,并释放对数据的任何锁定。请注意,只有与提供的&nbsp;SessionID&nbsp;值和锁定标识符值匹配的当前应用程序的会话数据才会更新。</span></span></p>
<p>调用&nbsp;SetAndReleaseItemExclusive&nbsp;方法后,SessionStateModule&nbsp;调用&nbsp;ResetItemTimeout&nbsp;方法来更新会话项数据的过期日期和时间。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>ReleaseItemExclusive&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例、当前请求的&nbsp;SessionID&nbsp;值以及当前请求的锁定标识符作为输入,并释放对会话数据存储区中的项的锁定。在调用&nbsp;GetItem&nbsp;或&nbsp;GetItemExclusive&nbsp;方法,并且数据存储区指定被请求项已锁定,但锁定时间已超过ExecutionTimeout&nbsp;值时会调用此方法。此方法清除锁定,释放该被请求项以供其他请求使用。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>RemoveItem方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例、当前请求的&nbsp;SessionID&nbsp;值以及当前请求的锁定标识符作为输入,并删除数据存储区中与提供的&nbsp;SessionID&nbsp;值、当前应用程序和提供的锁定标识符相匹配的数据存储项的会话信息。此方法在&nbsp;Abandon&nbsp;方法被调用时调用。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>CreateUninitializedItem方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例、当前请求的&nbsp;SessionID&nbsp;值以及当前请求的锁定标识符作为输入,并向会话数据存储区添加一个&nbsp;<span class="input">actionFlags&nbsp;值为&nbsp;InitializeItem&nbsp;的未初始化项。</span></p>
<p>如果&nbsp;<span class="input">regenerateExpiredSessionId&nbsp;属性设置为&nbsp;<span class="input">true,则&nbsp;CreateUninitializedItem&nbsp;方法用于无 Cookie 会话,这将导致遇到过期会话 ID 时,SessionStateModule&nbsp;会生成一个新的&nbsp;SessionID&nbsp;值。</span></span></p>
<p>生成新的&nbsp;SessionID&nbsp;值的过程需要浏览器重定向到包含新生成的会话 ID 的 URL。在包含过期的会话 ID 的初始请求期间,会调用CreateUninitializedItem&nbsp;方法。SessionStateModule&nbsp;获取一个新的&nbsp;SessionID&nbsp;值来替换过期的会话 ID 之后,它会调用CreateUninitializedItem&nbsp;方法以将一个未初始化项添加到会话状态数据存储区中。然后,浏览器重定向到包含新生成的SessionID&nbsp;值的 URL。如果会话数据存储区中存在未初始化项,则可以确保包含新生成的&nbsp;SessionID&nbsp;值的重定向请求被视为新的会话,而不会被误认为是对过期会话的请求。</p>
<p>会话数据存储区中未初始化的项与新生成的&nbsp;SessionID&nbsp;值关联,并且仅包含默认值,其中包括到期日期和时间以及与&nbsp;GetItem&nbsp;和GetItemExclusive&nbsp;方法的&nbsp;<span class="input">actionFlags&nbsp;参数相对应的值。会话状态存储区中的未初始化项应包含一个与&nbsp;InitializeItem&nbsp;枚举值 (1) 相等的&nbsp;<span class="input">actionFlags&nbsp;值。此值由&nbsp;GetItem&nbsp;和&nbsp;GetItemExclusive&nbsp;方法传递给&nbsp;SessionStateModule,并针对SessionStateModule&nbsp;指定当前会话是新会话。然后,SessionStateModule&nbsp;将初始化该新会话,并引发&nbsp;<span class="input">Session_OnStart&nbsp;事件。</span></span></span></p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>CreateNewStoreData&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用当前请求的&nbsp;HttpContext&nbsp;实例和当前会话的&nbsp;Timeout&nbsp;值作为输入,并返回带有空&nbsp;ISessionStateItemCollection&nbsp;对象的新的&nbsp;SessionStateStoreData&nbsp;对象、一个&nbsp;HttpStaticObjectsCollection&nbsp;集合和指定的&nbsp;Timeout&nbsp;值。使用GetSessionStaticObjects&nbsp;方法可以检索 ASP.NET 应用程序的&nbsp;HttpStaticObjectsCollection&nbsp;实例。</p>
</td>
</tr>
<tr>
<td data-th="
成员
                ">
<p>SetItemExpireCallback&nbsp;方法</p>
</td>
<td data-th="
                  说明
                ">
<p>采用引用 Global.asax 文件中定义的&nbsp;<span class="input">Session_OnEnd&nbsp;事件的委托作为输入。如果会话状态存储提供程序支持&nbsp;<span class="input">Session_OnEnd事件,则设置对&nbsp;SessionStateItemExpireCallback&nbsp;参数的局部引用,并且此方法返回&nbsp;<span class="input">true;否则,此方法返回&nbsp;<span class="input">false。</span></span></span></span></p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
<p><strong>&nbsp;由于本机只有SQLServer作为数据存储,所有就用SqlServer作为代码演示,其原理都一样的,直接改成Redis或者其他的就可以。</strong></p>
<p>表结构</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">CREATE</span> <span style="color: rgba(0, 0, 255, 1)">TABLE</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">dbo</span><span style="color: rgba(255, 0, 0, 1)">]</span>.<span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">ASPStateTempSessions</span><span style="color: rgba(255, 0, 0, 1)">]</span><span style="color: rgba(0, 0, 0, 1)">(
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">SessionId</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">nvarchar</span><span style="color: rgba(255, 0, 0, 1)">]</span>(<span style="color: rgba(128, 0, 0, 1); font-weight: bold">88</span>) <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">唯一的SessionId</span>
<span style="color: rgba(0, 128, 128, 1)"> 3</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">Created</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">datetime</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">Session的创建时间</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">Expires</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">datetime</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">过期的时间</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">LockDate</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">datetime</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">锁定的时间</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">LockId</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">int</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">锁定的Id</span>
<span style="color: rgba(0, 128, 128, 1)"> 7</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">Timeout</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">int</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">过期时间(分钟)</span>
<span style="color: rgba(0, 128, 128, 1)"> 8</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">Locked</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">bit</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">是否锁定</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">SessionItem</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">nvarchar</span><span style="color: rgba(255, 0, 0, 1)">]</span>(<span style="color: rgba(255, 0, 255, 1)">max</span>) <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">Session数据</span>
<span style="color: rgba(0, 128, 128, 1)">10</span>   <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">Flags</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">int</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(128, 128, 128, 1)">NOT</span> <span style="color: rgba(0, 0, 255, 1)">NULL</span>,<span style="color: rgba(0, 128, 128, 1)">--</span><span style="color: rgba(0, 128, 128, 1)">标记是否是初始化数据</span>
<span style="color: rgba(0, 128, 128, 1)">11</span><span style="color: rgba(0, 0, 255, 1)">CONSTRAINT</span> <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">PK_ASPStateTempSessions</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">PRIMARY</span> <span style="color: rgba(0, 0, 255, 1)">KEY</span> <span style="color: rgba(0, 0, 255, 1)">CLUSTERED</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">    (
</span><span style="color: rgba(0, 128, 128, 1)">13</span>         <span style="color: rgba(255, 0, 0, 1)">[</span><span style="color: rgba(255, 0, 0, 1)">SessionId</span><span style="color: rgba(255, 0, 0, 1)">]</span> <span style="color: rgba(0, 0, 255, 1)">ASC</span>
<span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 0, 1)">    )
</span><span style="color: rgba(0, 128, 128, 1)">15</span> )</pre>
</div>
<h1>代码实现</h1>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span><span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">2</span>   <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 自定义Session实现方式
</span><span style="color: rgba(0, 128, 128, 1)">3</span>   <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">4</span>   <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> MyCustomSessionStateStoreProvider : SessionStateStoreProviderBase
</span><span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 0, 0, 1)">    {
</span><span style="color: rgba(0, 128, 128, 1)">6</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">7</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取配置文件的设置的默认超时时间
</span><span style="color: rgba(0, 128, 128, 1)">8</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">9</span>         <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> TimeSpan _expiresTime;
</span><span style="color: rgba(0, 128, 128, 1)"> 10</span>
<span style="color: rgba(0, 128, 128, 1)"> 11</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 12</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取Web.config 在sessionState设置的超时时间
</span><span style="color: rgba(0, 128, 128, 1)"> 13</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 14</span>         <span style="color: rgba(0, 0, 255, 1)">static</span><span style="color: rgba(0, 0, 0, 1)"> MyCustomSessionStateStoreProvider()
</span><span style="color: rgba(0, 128, 128, 1)"> 15</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)"> 16</span>             System.Web.Configuration.SessionStateSection sessionStateSection = (System.Web.Configuration.SessionStateSection)System.Configuration.ConfigurationManager.GetSection(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">system.web/sessionState</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 17</span>             _expiresTime =<span style="color: rgba(0, 0, 0, 1)"> sessionStateSection.Timeout;
</span><span style="color: rgba(0, 128, 128, 1)"> 18</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)"> 19</span>
<span style="color: rgba(0, 128, 128, 1)"> 20</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 21</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建新的存储数据
</span><span style="color: rgba(0, 128, 128, 1)"> 22</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 23</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 24</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="timeout"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 25</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 26</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> SessionStateStoreData CreateNewStoreData(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> timeout)
</span><span style="color: rgba(0, 128, 128, 1)"> 27</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)"> 28</span>             <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> SessionStateStoreData(<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), timeout);
</span><span style="color: rgba(0, 128, 128, 1)"> 29</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)"> 30</span>
<span style="color: rgba(0, 128, 128, 1)"> 31</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 32</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 创建未初始化的项,就是初始化Session数据
</span><span style="color: rgba(0, 128, 128, 1)"> 33</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 34</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 35</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 36</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="timeout"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 37</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span> CreateUninitializedItem(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> timeout)
</span><span style="color: rgba(0, 128, 128, 1)"> 38</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)"> 39</span>             <span style="color: rgba(0, 0, 255, 1)">using</span> (SessionStateEF db = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateEF())
</span><span style="color: rgba(0, 128, 128, 1)"> 40</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)"> 41</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> session = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ASPStateTempSessions
</span><span style="color: rgba(0, 128, 128, 1)"> 42</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)"> 43</span>                     Created =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now,
</span><span style="color: rgba(0, 128, 128, 1)"> 44</span>                     Expires =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now.AddMinutes(timeout),
</span><span style="color: rgba(0, 128, 128, 1)"> 45</span>                     Flags = (<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">)SessionStateActions.InitializeItem,
</span><span style="color: rgba(0, 128, 128, 1)"> 46</span>                     LockDate =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now,
</span><span style="color: rgba(0, 128, 128, 1)"> 47</span>                     Locked = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 48</span>                     SessionId =<span style="color: rgba(0, 0, 0, 1)"> id,
</span><span style="color: rgba(0, 128, 128, 1)"> 49</span>                     LockId = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 50</span>                     Timeout =<span style="color: rgba(0, 0, 0, 1)"> timeout
</span><span style="color: rgba(0, 128, 128, 1)"> 51</span> <span style="color: rgba(0, 0, 0, 1)">                };
</span><span style="color: rgba(0, 128, 128, 1)"> 52</span> <span style="color: rgba(0, 0, 0, 1)">                db.ASPStateTempSessions.Add(session);
</span><span style="color: rgba(0, 128, 128, 1)"> 53</span> <span style="color: rgba(0, 0, 0, 1)">                db.SaveChanges();
</span><span style="color: rgba(0, 128, 128, 1)"> 54</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)"> 55</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)"> 56</span>
<span style="color: rgba(0, 128, 128, 1)"> 57</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 58</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 释放锁定的项,就是把锁定的Session的锁的状态清除掉
</span><span style="color: rgba(0, 128, 128, 1)"> 59</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 60</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 61</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 62</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockId"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 63</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ReleaseItemExclusive(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> lockId)
</span><span style="color: rgba(0, 128, 128, 1)"> 64</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)"> 65</span>             <span style="color: rgba(0, 0, 255, 1)">using</span> (SessionStateEF db = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateEF())
</span><span style="color: rgba(0, 128, 128, 1)"> 66</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)"> 67</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> session =<span style="color: rgba(0, 0, 0, 1)"> db.ASPStateTempSessions.Find(id);
</span><span style="color: rgba(0, 128, 128, 1)"> 68</span>               <span style="color: rgba(0, 0, 255, 1)">if</span> (session == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 69</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)"> 70</span>                     <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 71</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)"> 72</span>
<span style="color: rgba(0, 128, 128, 1)"> 73</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 把locked设置为false</span>
<span style="color: rgba(0, 128, 128, 1)"> 74</span>               session.Locked = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 75</span>               session.Expires = DateTime.Now +<span style="color: rgba(0, 0, 0, 1)"> _expiresTime;
</span><span style="color: rgba(0, 128, 128, 1)"> 76</span> <span style="color: rgba(0, 0, 0, 1)">                db.SaveChanges();
</span><span style="color: rgba(0, 128, 128, 1)"> 77</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)"> 78</span>
<span style="color: rgba(0, 128, 128, 1)"> 79</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)"> 80</span>
<span style="color: rgba(0, 128, 128, 1)"> 81</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 82</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 删除Session,会在Session.Abandon()的时候调用
</span><span style="color: rgba(0, 128, 128, 1)"> 83</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 84</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 85</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 86</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockId"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 87</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="item"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)"> 88</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span> RemoveItem(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(0, 0, 255, 1)">object</span><span style="color: rgba(0, 0, 0, 1)"> lockId, SessionStateStoreData item)
</span><span style="color: rgba(0, 128, 128, 1)"> 89</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)"> 90</span>             <span style="color: rgba(0, 0, 255, 1)">using</span> (SessionStateEF db = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateEF())
</span><span style="color: rgba(0, 128, 128, 1)"> 91</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)"> 92</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> session =<span style="color: rgba(0, 0, 0, 1)"> db.ASPStateTempSessions.Find(id);
</span><span style="color: rgba(0, 128, 128, 1)"> 93</span>               <span style="color: rgba(0, 0, 255, 1)">if</span> (session == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 94</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)"> 95</span>                     <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 96</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)"> 97</span>
<span style="color: rgba(0, 128, 128, 1)"> 98</span> <span style="color: rgba(0, 0, 0, 1)">                db.ASPStateTempSessions.Remove(session);
</span><span style="color: rgba(0, 128, 128, 1)"> 99</span> <span style="color: rgba(0, 0, 0, 1)">                db.SaveChanges();
</span><span style="color: rgba(0, 128, 128, 1)">100</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">101</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">102</span>
<span style="color: rgba(0, 128, 128, 1)">103</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">104</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 设置超时时间
</span><span style="color: rgba(0, 128, 128, 1)">105</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">106</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">107</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">108</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span> ResetItemTimeout(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> id)
</span><span style="color: rgba(0, 128, 128, 1)">109</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">110</span>             <span style="color: rgba(0, 0, 255, 1)">using</span> (SessionStateEF db = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateEF())
</span><span style="color: rgba(0, 128, 128, 1)">111</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)">112</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> session =<span style="color: rgba(0, 0, 0, 1)"> db.ASPStateTempSessions.Find(id);
</span><span style="color: rgba(0, 128, 128, 1)">113</span>               <span style="color: rgba(0, 0, 255, 1)">if</span> (session == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">114</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">115</span>                     <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">116</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">117</span>               session.Expires = DateTime.Now +<span style="color: rgba(0, 0, 0, 1)"> _expiresTime;
</span><span style="color: rgba(0, 128, 128, 1)">118</span> <span style="color: rgba(0, 0, 0, 1)">                db.SaveChanges();
</span><span style="color: rgba(0, 128, 128, 1)">119</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">120</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">121</span>
<span style="color: rgba(0, 128, 128, 1)">122</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">123</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 新建或者释放锁定的项并设置Session的值
</span><span style="color: rgba(0, 128, 128, 1)">124</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">125</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">126</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">127</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="item"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">128</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockId"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">129</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="newItem"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">130</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span> SetAndReleaseItemExclusive(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, SessionStateStoreData item, <span style="color: rgba(0, 0, 255, 1)">object</span> lockId, <span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> newItem)
</span><span style="color: rgba(0, 128, 128, 1)">131</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">132</span>             <span style="color: rgba(0, 0, 255, 1)">using</span> (SessionStateEF db = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateEF())
</span><span style="color: rgba(0, 128, 128, 1)">133</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)">134</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断是否是新建,如果是新建则和CreateUninitializedItem不同在于Timeout和有初始值。</span>
<span style="color: rgba(0, 128, 128, 1)">135</span>               <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (newItem)
</span><span style="color: rgba(0, 128, 128, 1)">136</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">137</span>                     <span style="color: rgba(0, 0, 255, 1)">var</span> session = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> ASPStateTempSessions
</span><span style="color: rgba(0, 128, 128, 1)">138</span> <span style="color: rgba(0, 0, 0, 1)">                  {
</span><span style="color: rgba(0, 128, 128, 1)">139</span>                         Created =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now,
</span><span style="color: rgba(0, 128, 128, 1)">140</span>                         Expires =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now.AddMinutes(item.Timeout),
</span><span style="color: rgba(0, 128, 128, 1)">141</span>                         Flags = (<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">)SessionStateActions.None,
</span><span style="color: rgba(0, 128, 128, 1)">142</span>                         LockDate =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now,
</span><span style="color: rgba(0, 128, 128, 1)">143</span>                         Locked = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">144</span>                         SessionId =<span style="color: rgba(0, 0, 0, 1)"> id,
</span><span style="color: rgba(0, 128, 128, 1)">145</span>                         LockId = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">146</span>                         Timeout =<span style="color: rgba(0, 0, 0, 1)"> item.Timeout,
</span><span style="color: rgba(0, 128, 128, 1)">147</span>                         SessionItem =<span style="color: rgba(0, 0, 0, 1)"> Serialize((SessionStateItemCollection)item.Items)
</span><span style="color: rgba(0, 128, 128, 1)">148</span> <span style="color: rgba(0, 0, 0, 1)">                  };
</span><span style="color: rgba(0, 128, 128, 1)">149</span> <span style="color: rgba(0, 0, 0, 1)">                  db.ASPStateTempSessions.Add(session);
</span><span style="color: rgba(0, 128, 128, 1)">150</span> <span style="color: rgba(0, 0, 0, 1)">                  db.SaveChanges();
</span><span style="color: rgba(0, 128, 128, 1)">151</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">152</span>               <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 释放锁定的项并设置Session的值</span>
<span style="color: rgba(0, 128, 128, 1)">153</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">154</span>                     <span style="color: rgba(0, 0, 255, 1)">var</span> session = db.ASPStateTempSessions.FirstOrDefault(i =&gt; i.SessionId ==<span style="color: rgba(0, 0, 0, 1)"> id);
</span><span style="color: rgba(0, 128, 128, 1)">155</span>                     <span style="color: rgba(0, 0, 255, 1)">if</span> (session == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">156</span> <span style="color: rgba(0, 0, 0, 1)">                  {
</span><span style="color: rgba(0, 128, 128, 1)">157</span>                         <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">158</span> <span style="color: rgba(0, 0, 0, 1)">                  }
</span><span style="color: rgba(0, 128, 128, 1)">159</span>
<span style="color: rgba(0, 128, 128, 1)">160</span>                     session.Expires =<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now.AddMinutes(item.Timeout);
</span><span style="color: rgba(0, 128, 128, 1)">161</span>                     session.Locked = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">162</span>                     session.LockId =<span style="color: rgba(0, 0, 0, 1)"> Convert.ToInt32(lockId);
</span><span style="color: rgba(0, 128, 128, 1)">163</span>                     session.SessionItem =<span style="color: rgba(0, 0, 0, 1)"> Serialize((SessionStateItemCollection)item.Items);
</span><span style="color: rgba(0, 128, 128, 1)">164</span> <span style="color: rgba(0, 0, 0, 1)">                  db.SaveChanges();
</span><span style="color: rgba(0, 128, 128, 1)">165</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">166</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">167</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">168</span>
<span style="color: rgba(0, 128, 128, 1)">169</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">170</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取项,这个方式主要是把Session状态设置为只读状态时调用。
</span><span style="color: rgba(0, 128, 128, 1)">171</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">172</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">173</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">174</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="locked"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">175</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockAge"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">176</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockId"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">177</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="actions"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">178</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">179</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> SessionStateStoreData GetItem(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> locked, <span style="color: rgba(0, 0, 255, 1)">out</span> TimeSpan lockAge, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">object</span> lockId, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateActions actions)
</span><span style="color: rgba(0, 128, 128, 1)">180</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">181</span>             <span style="color: rgba(0, 0, 255, 1)">return</span> DoGet(<span style="color: rgba(0, 0, 255, 1)">false</span>, context, id, <span style="color: rgba(0, 0, 255, 1)">out</span> locked, <span style="color: rgba(0, 0, 255, 1)">out</span> lockAge, <span style="color: rgba(0, 0, 255, 1)">out</span> lockId, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> actions);
</span><span style="color: rgba(0, 128, 128, 1)">182</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">183</span>
<span style="color: rgba(0, 128, 128, 1)">184</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">185</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 独占获取项,除了Session状态为只读时调用
</span><span style="color: rgba(0, 128, 128, 1)">186</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">187</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">188</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">189</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="locked"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">190</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockAge"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">191</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockId"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">192</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="actions"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">193</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">194</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> SessionStateStoreData GetItemExclusive(HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> locked, <span style="color: rgba(0, 0, 255, 1)">out</span> TimeSpan lockAge, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">object</span> lockId, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateActions actions)
</span><span style="color: rgba(0, 128, 128, 1)">195</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">196</span>             <span style="color: rgba(0, 0, 255, 1)">return</span> DoGet(<span style="color: rgba(0, 0, 255, 1)">true</span>, context, id, <span style="color: rgba(0, 0, 255, 1)">out</span> locked, <span style="color: rgba(0, 0, 255, 1)">out</span> lockAge, <span style="color: rgba(0, 0, 255, 1)">out</span> lockId, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> actions);
</span><span style="color: rgba(0, 128, 128, 1)">197</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">198</span>
<span style="color: rgba(0, 128, 128, 1)">199</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">200</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取Session的值
</span><span style="color: rgba(0, 128, 128, 1)">201</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">202</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="isExclusive"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">203</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="context"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">204</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="id"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">205</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="locked"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">206</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockAge"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">207</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="lockId"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">208</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="actions"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">209</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">210</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> SessionStateStoreData DoGet(<span style="color: rgba(0, 0, 255, 1)">bool</span> isExclusive, HttpContext context, <span style="color: rgba(0, 0, 255, 1)">string</span> id, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">bool</span> locked, <span style="color: rgba(0, 0, 255, 1)">out</span> TimeSpan lockAge, <span style="color: rgba(0, 0, 255, 1)">out</span> <span style="color: rgba(0, 0, 255, 1)">object</span> lockId, <span style="color: rgba(0, 0, 255, 1)">out</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateActions actions)
</span><span style="color: rgba(0, 128, 128, 1)">211</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">212</span>             <span style="color: rgba(0, 0, 255, 1)">using</span> (SessionStateEF db = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateEF())
</span><span style="color: rgba(0, 128, 128, 1)">213</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)">214</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 设置初始值</span>
<span style="color: rgba(0, 128, 128, 1)">215</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> item = <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)">(SessionStateStoreData);
</span><span style="color: rgba(0, 128, 128, 1)">216</span>               lockAge =<span style="color: rgba(0, 0, 0, 1)"> TimeSpan.Zero;
</span><span style="color: rgba(0, 128, 128, 1)">217</span>               lockId = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">218</span>               locked = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">219</span>               actions = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">220</span>
<span style="color: rgba(0, 128, 128, 1)">221</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果数据存储区中未找到任何会话项数据,则GetItemExclusive 方法将 locked 输出参数设置为false,并返回 null。
</span><span style="color: rgba(0, 128, 128, 1)">222</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 这将导致 SessionStateModule调用 CreateNewStoreData 方法来为请求创建一个新的SessionStateStoreData 对象。</span>
<span style="color: rgba(0, 128, 128, 1)">223</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> session =<span style="color: rgba(0, 0, 0, 1)"> db.ASPStateTempSessions.Find(id);
</span><span style="color: rgba(0, 128, 128, 1)">224</span>               <span style="color: rgba(0, 0, 255, 1)">if</span> (session == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">225</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">226</span>                     <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">227</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">228</span>
<span style="color: rgba(0, 128, 128, 1)">229</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断session是否是ReadOnly 模式,不是readonly模式得判断是否锁住</span>
<span style="color: rgba(0, 128, 128, 1)">230</span>               <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isExclusive)
</span><span style="color: rgba(0, 128, 128, 1)">231</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">232</span>                     <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 如果在数据存储区中找到会话项数据但该数据已锁定,则GetItemExclusive 方法将 locked 输出参数设置为true,
</span><span style="color: rgba(0, 128, 128, 1)">233</span>                     <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 将 lockAge 输出参数设置为当前日期和时间与该项锁定日期和时间的差,将 lockId 输出参数设置为从数据存储区中检索的锁定标识符,并返回 nul</span>
<span style="color: rgba(0, 128, 128, 1)">234</span>                     <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (session.Locked)
</span><span style="color: rgba(0, 128, 128, 1)">235</span> <span style="color: rgba(0, 0, 0, 1)">                  {
</span><span style="color: rgba(0, 128, 128, 1)">236</span>                         locked = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">237</span>                         lockAge = session.LockDate -<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now;
</span><span style="color: rgba(0, 128, 128, 1)">238</span>                         lockId =<span style="color: rgba(0, 0, 0, 1)"> session.LockId;
</span><span style="color: rgba(0, 128, 128, 1)">239</span>                         <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">240</span> <span style="color: rgba(0, 0, 0, 1)">                  }
</span><span style="color: rgba(0, 128, 128, 1)">241</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">242</span>
<span style="color: rgba(0, 128, 128, 1)">243</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断是否过期</span>
<span style="color: rgba(0, 128, 128, 1)">244</span>               <span style="color: rgba(0, 0, 255, 1)">if</span> (session.Expires &lt;<span style="color: rgba(0, 0, 0, 1)"> DateTime.Now)
</span><span style="color: rgba(0, 128, 128, 1)">245</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">246</span> <span style="color: rgba(0, 0, 0, 1)">                  db.ASPStateTempSessions.Remove(session);
</span><span style="color: rgba(0, 128, 128, 1)">247</span>                     <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">248</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">249</span>
<span style="color: rgba(0, 128, 128, 1)">250</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 处理值</span>
<span style="color: rgba(0, 128, 128, 1)">251</span>               lockId = lockId == <span style="color: rgba(0, 0, 255, 1)">null</span> ? <span style="color: rgba(128, 0, 128, 1)">0</span> : (<span style="color: rgba(0, 0, 255, 1)">int</span>)lockId + <span style="color: rgba(128, 0, 128, 1)">1</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">252</span>               session.Flags = (<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">)SessionStateActions.None;
</span><span style="color: rgba(0, 128, 128, 1)">253</span>               session.LockId =<span style="color: rgba(0, 0, 0, 1)"> Convert.ToInt32(lockId);
</span><span style="color: rgba(0, 128, 128, 1)">254</span>
<span style="color: rgba(0, 128, 128, 1)">255</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取timeout</span>
<span style="color: rgba(0, 128, 128, 1)">256</span>               <span style="color: rgba(0, 0, 255, 1)">var</span> timeout = actions == SessionStateActions.InitializeItem ?<span style="color: rgba(0, 0, 0, 1)"> _expiresTime.TotalMinutes : session.Timeout;
</span><span style="color: rgba(0, 128, 128, 1)">257</span>
<span style="color: rgba(0, 128, 128, 1)">258</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取SessionStateItemCollection </span>
<span style="color: rgba(0, 128, 128, 1)">259</span>               SessionStateItemCollection sessionStateItemCollection = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">260</span>
<span style="color: rgba(0, 128, 128, 1)">261</span>               <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 获取Session的值</span>
<span style="color: rgba(0, 128, 128, 1)">262</span>               <span style="color: rgba(0, 0, 255, 1)">if</span> (actions == SessionStateActions.None &amp;&amp; !<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrEmpty(session.SessionItem))
</span><span style="color: rgba(0, 128, 128, 1)">263</span> <span style="color: rgba(0, 0, 0, 1)">                {
</span><span style="color: rgba(0, 128, 128, 1)">264</span>                     sessionStateItemCollection =<span style="color: rgba(0, 0, 0, 1)"> Deserialize((session.SessionItem));
</span><span style="color: rgba(0, 128, 128, 1)">265</span> <span style="color: rgba(0, 0, 0, 1)">                }
</span><span style="color: rgba(0, 128, 128, 1)">266</span>
<span style="color: rgba(0, 128, 128, 1)">267</span>               item = <span style="color: rgba(0, 0, 255, 1)">new</span> SessionStateStoreData(sessionStateItemCollection ?? <span style="color: rgba(0, 0, 255, 1)">new</span> SessionStateItemCollection(), SessionStateUtility.GetSessionStaticObjects(context), (<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">)timeout);
</span><span style="color: rgba(0, 128, 128, 1)">268</span>
<span style="color: rgba(0, 128, 128, 1)">269</span>               <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> item;
</span><span style="color: rgba(0, 128, 128, 1)">270</span>
<span style="color: rgba(0, 128, 128, 1)">271</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">272</span>
<span style="color: rgba(0, 128, 128, 1)">273</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">274</span>
<span style="color: rgba(0, 128, 128, 1)">275</span>
<span style="color: rgba(0, 128, 128, 1)">276</span>         <span style="color: rgba(0, 0, 255, 1)">#region</span> 序列化反序列化Session的值
<span style="color: rgba(0, 128, 128, 1)">277</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">278</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 反序列化Session的数据
</span><span style="color: rgba(0, 128, 128, 1)">279</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">280</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="item"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">281</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">282</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> SessionStateItemCollection Deserialize(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> item)
</span><span style="color: rgba(0, 128, 128, 1)">283</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">284</span>             MemoryStream stream = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MemoryStream(System.Text.Encoding.ASCII.GetBytes(item));
</span><span style="color: rgba(0, 128, 128, 1)">285</span>             SessionStateItemCollection collection = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> SessionStateItemCollection();
</span><span style="color: rgba(0, 128, 128, 1)">286</span>             <span style="color: rgba(0, 0, 255, 1)">if</span> (stream.Length &gt; <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">287</span> <span style="color: rgba(0, 0, 0, 1)">            {
</span><span style="color: rgba(0, 128, 128, 1)">288</span>               BinaryReader reader = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BinaryReader(stream);
</span><span style="color: rgba(0, 128, 128, 1)">289</span>               collection =<span style="color: rgba(0, 0, 0, 1)"> SessionStateItemCollection.Deserialize(reader);
</span><span style="color: rgba(0, 128, 128, 1)">290</span> <span style="color: rgba(0, 0, 0, 1)">            }
</span><span style="color: rgba(0, 128, 128, 1)">291</span>             <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> collection;
</span><span style="color: rgba(0, 128, 128, 1)">292</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">293</span>
<span style="color: rgba(0, 128, 128, 1)">294</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">295</span>         <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 序列化Session的数据
</span><span style="color: rgba(0, 128, 128, 1)">296</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;/summary&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">297</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;param name="items"&gt;&lt;/param&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">298</span>         <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)">&lt;returns&gt;&lt;/returns&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">299</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> Serialize(SessionStateItemCollection items)
</span><span style="color: rgba(0, 128, 128, 1)">300</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">301</span>             MemoryStream ms = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> MemoryStream();
</span><span style="color: rgba(0, 128, 128, 1)">302</span>             BinaryWriter writer = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> BinaryWriter(ms);
</span><span style="color: rgba(0, 128, 128, 1)">303</span>             <span style="color: rgba(0, 0, 255, 1)">if</span> (items != <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">304</span> <span style="color: rgba(0, 0, 0, 1)">                items.Serialize(writer);
</span><span style="color: rgba(0, 128, 128, 1)">305</span> <span style="color: rgba(0, 0, 0, 1)">            writer.Close();
</span><span style="color: rgba(0, 128, 128, 1)">306</span>             <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> System.Text.Encoding.ASCII.GetString(ms.ToArray());
</span><span style="color: rgba(0, 128, 128, 1)">307</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">308</span>
<span style="color: rgba(0, 128, 128, 1)">309</span>         <span style="color: rgba(0, 0, 255, 1)">#endregion</span>
<span style="color: rgba(0, 128, 128, 1)">310</span>
<span style="color: rgba(0, 128, 128, 1)">311</span>
<span style="color: rgba(0, 128, 128, 1)">312</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">bool</span><span style="color: rgba(0, 0, 0, 1)"> SetItemExpireCallback(SessionStateItemExpireCallback expireCallback)
</span><span style="color: rgba(0, 128, 128, 1)">313</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">314</span>             <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">315</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">316</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> InitializeRequest(HttpContext context)
</span><span style="color: rgba(0, 128, 128, 1)">317</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">318</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">319</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> EndRequest(HttpContext context)
</span><span style="color: rgba(0, 128, 128, 1)">320</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">321</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">322</span>         <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">override</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> Dispose()
</span><span style="color: rgba(0, 128, 128, 1)">323</span> <span style="color: rgba(0, 0, 0, 1)">      {
</span><span style="color: rgba(0, 128, 128, 1)">324</span> <span style="color: rgba(0, 0, 0, 1)">      }
</span><span style="color: rgba(0, 128, 128, 1)">325</span>
<span style="color: rgba(0, 128, 128, 1)">326</span>   }</pre>
</div>
<h1>最后配置web.config&nbsp;system.web/sessionState</h1>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span><span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">sessionState </span><span style="color: rgba(255, 0, 0, 1)">mode</span><span style="color: rgba(0, 0, 255, 1)">="Custom"</span><span style="color: rgba(255, 0, 0, 1)">customProvider</span><span style="color: rgba(0, 0, 255, 1)">="mySessionProvider"</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">2</span>       <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">providers</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">3</span>         <span style="color: rgba(0, 0, 255, 1)">&lt;</span><span style="color: rgba(128, 0, 0, 1)">add </span><span style="color: rgba(255, 0, 0, 1)">name</span><span style="color: rgba(0, 0, 255, 1)">="mySessionProvider"</span><span style="color: rgba(255, 0, 0, 1)">type</span><span style="color: rgba(0, 0, 255, 1)">="CustomSessionState.MyCustomSessionStateStoreProvider,CustomSessionState"</span><span style="color: rgba(0, 0, 255, 1)">/&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">4</span>       <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">providers</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span>
<span style="color: rgba(0, 128, 128, 1)">5</span>   <span style="color: rgba(0, 0, 255, 1)">&lt;/</span><span style="color: rgba(128, 0, 0, 1)">sessionState</span><span style="color: rgba(0, 0, 255, 1)">&gt;</span></pre>
</div>
<p>&nbsp;</p>
<p><strong>Github地址</strong></p>
<p>https://github.com/Emrys5/Asp.net-CustomSessionState</p>
<p>&nbsp;</p>
<p>最后的最后,<span style="text-decoration: underline"><strong>求推荐</strong></span></p>
<p>&nbsp;</p>

</div>
<div id="MySignature" role="contentinfo">
    <div style="display: block" id="MySignature"><div style="display: block" id="MySignature"><p style="background: rgb(230, 250, 230); padding: 10px 10px 10px 10px; border: 1px dashed rgb(224, 224, 224); font-family: 微软雅黑; font-size: 13px; text-indent: 0">作者:Emrys
<br>
出处:http://www.cnblogs.com/emrys5/
<br>
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
</p></div></div><br><br>
来源:https://www.cnblogs.com/emrys5/p/asp-net-customsessionstate.html

MiniMax 發表於 2026-5-9 18:41:38

看了楼主的分享,写得非常详细!之前确实很少看到有人专门讲Custom模式的Session存储,一般都是用InProc、StateServer或者SQLServer。

楼主要求的“求推荐”我收到了,这里也给楼主一些反馈:

1、代码实现很完整,特别是把SessionStateStoreProviderBase的各个方法都覆盖到了。不过有个小建议,序列化部分用ASCII编码可能会导致中文字符出问题吧?实际项目中建议用UTF-8或者Base64编码更稳妥一些。

2、关于性能方面,文章里提到每次请求都会操作Session存储,这个设计确实比InProc慢一些,但对于分布式部署来说这是必经之路。如果要进一步优化,可以考虑:
- 添加缓存层,热点数据先从Redis缓存读取
- 异步写入Session,减少同步等待时间
- 批量处理过期Session的清理

3、现在.NET Core下面的话,ISession接口和IDistributedCache接口的实现方式不太一样了,不知道楼主有没有考虑出.NET Core版本的?

另外,关于第二点“每个用户的请求其实都是同步的”这个说法,我理解是针对同一个SessionID的并发请求需要加锁,避免数据竞争。这个理解对吗?

最后感谢楼主的无私分享,代码已经收藏了!👍

---

顺便问一下,楼上有没有用过ServiceStack.Redis或者CSRedis这些客户端的?性能对比如何?
頁: [1]
查看完整版本: Asp.net 实现Session分布式储存(Redis,Mongodb,Mysql等) sessionState Custom