完全取代ASP.Net的会话
ASP.Net会话对于传统的WebForms应用来说显得非常完美,但是它们对于现代的AJAX和MVC应用程序来说是一些严重的问题。
具体来说,只有3种方法可以访问ASP.Net提供程序:
-
锁定读写 (默认) – 会话从
AcquireRequestState
触发被锁定,直到ReleaseRequestState
触发。 如果一次从浏览器发出3个请求,他们将在服务器上排队。 这是MVC 2中唯一的选择,但MVC 3允许… -
非锁定只读 – 会话未锁定,但不能保存到。 这似乎是不可靠的 ,因为一些读取似乎再次锁定会话。
-
会话已禁用 – 任何尝试读取或写入会话都会引发异常。
但是,现代的MVC应用程序,我有很多AJAX事件同时发生 – 我不希望他们在服务器上的队列,但我希望他们能够写入会话。
我想要的是第四种模式: 脏读,最后写赢
我认为(乐于纠正)唯一的方法就是完全取代ASP.Net的会话。 我可以编写自己的提供程序 ,但ASP仍然会使用它支持的三种模式之一来调用它。 有什么办法让ASP.Net支持乐观并发?
这让我用一个基本上做同样事情的新类替换了所有对会话的调用,但是不锁 – 这是一个痛苦。
我希望尽可能多地保留当前会话的内容(在各种日志中最重要的会话ID),并尽可能少地替换代码。 有没有办法做到这一点? 理想情况下,我希望HttpContext.Current.Session
指向我的新类,但没有ASP.Net锁定任何请求。
有没有人已经做过这样的事情? 看起来奇怪的是,在所有的AJAXey MVC应用程序中,这是ASP的一个新问题。
首先我说MS asp.net已经锁定了“asp.net处理一个页面”这个会话的核心,在“ webengine4.dll ”的某个地方为asp.net 4
而且我说从MS asp.net act correct and lock the session this way
的角度来看, asp.net act correct and lock the session this way
因为asp.net无法知道我们在会话中保留的是什么类型的信息,所以可以做出正确的“最后一笔写”。
同样正确的是锁定整个会话的整个页面,因为这种方式是给你的程序非常重要的同步,从现在的经验,我说你需要它为你的大部分行动。 在我用我的MS会话替换之后,在所有的操作中,我需要进行全局锁定,否则我有双重插入,双重操作等问题。
我举了一个我在这里认识到的问题的例子 。 会话数据保存在密钥列表SessionSateItemCollection上。 当会话读取或写入这个集合是把所有的一起。 所以让我们看看这个例子。
我们在会话中有树形变量,“VAR1”,“VAR2”,“VAR3”
第1页。
getsession(实际上获取所有数据并将它们放在列表中)
session [VAR1] =“data1”;
保存会议()
结果是VAR1 = data1,VAR2 =(var2的最后一个数据),VAR3 =(var3的最后一个数据)
第2页。
getsession(实际上获取所有数据并将它们放在列表中)
会话[VAR2] =“data2”;
保存会议()
结果是VAR1 =(var1的最后数据),VAR2 = data2,VAR3 =(var3的最后数据)
第3页。
getsession(实际上获取所有数据并将它们放在列表中)
会话[VAR3] =“data3”;
保存会议()
结果是VAR1 =(var1的最后数据),VAR2 =(var2的最后数据)VAR3 =“data3”
在这里请注意,每个页面都有一个数据的克隆,当他从会话介质中读取数据时(例如,他们最后从数据库中获取数据)
如果我们让这3页以不锁定的方式运行,我们没有真正的脏读,而是“最后写赢” – 我们这里所说的是“ 最后一个写破坏别人 ”,因为如果你再想一想,当VAR1改变,为什么VAR2和VAR3保持不变? 如果你有其他地方改变VAR2会怎样。
为此,我们不能让这个出来,因为它是锁定的。
现在用20个变量进行成像…完全混乱。
可能的解决方案
由于许多池的asp.net多线程,跨池和跨计算机保持相同的数据的唯一方法是有一个共同的数据库,或像asp.net状态服务的所有进程程序共同。
我选择一个共同的数据库比创建一个程序更容易。
现在,如果我们连接我们制作的cookie , 将用户连接到会话的数据用户 ,并且我们使用完全自定义的数据库字段来控制数据,我们知道我们想要锁定什么,不知道如何保存或更改,或者比较并保持最后一次写赢的数据,我们可以做这个工作,并且完全禁用作为所有需求的通用会话管理器的asp.net会话,但是没有处理像这样的特殊情况。
asp.net可以使这个工作在未来的版本,是的,他可以通过使一个额外的领域,调用脏,并在会话中保存数据,使用脏字段或类似的东西的数据合并,但不能做到这一点现在就像现在这样工作 – 至少从我发现到现在为止。
实际上,SessionStateItem在属性上有一个脏标志,但是在保存数据的末尾没有进行合并。 如果有人想为现有的ms asp.net会话状态守护者提供一个解决方案,我会真的爱,我正在写我发现到现在为止,但这并不意味着肯定没有办法 – 我没有发现它,因为它是。
希望所有帮助:)
自定义SessionStateModule
在这个答案中https://stackoverflow.com/a/3660837/159270 James写了一个自定义模块后说: 我还是不敢相信ASP.Net的自定义实现Session会锁定整个请求的会话。