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