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