完全替换 ASP.Net 的会话 [英] Replacing ASP.Net's session entirely

查看:24
本文介绍了完全替换 ASP.Net 的会话的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ASP.Net session 看起来非常适合传统的 WebForms 应用程序,但它们做了一些对于现代 AJAX 和 MVC 应用程序来说很严重的问题.

ASP.Net session appear perfect for a traditional WebForms app, but they do some things that are a serious problem for a modern AJAX and MVC application.

具体来说,只有 3 种方法可以访问 ASP.Net 提供程序:

Specifically there are only 3 ways to access the ASP.Net provider:

  1. 锁定读取&write(默认) - 会话被锁定,从 AcquireRequestState 触发直到 ReleaseRequestState 触发.如果浏览器同时发出 3 个请求,它们将在服务器上排队.这是 MVC 2 中唯一的选项,但 MVC 3 允许...

  1. Locking read & write (default) - the session is locked from AcquireRequestState firing until ReleaseRequestState fires. If 3 requests occur from the browser at once they'll queue up on the server. This is the only option in MVC 2, but MVC 3 allows...

非锁定只读 - 会话未锁定,但无法保存到.这似乎不可靠,因为有些读取似乎再次锁定会话.

Non-locking read only - the session isn't locked, but can't be saved to. This appears to be unreliable though, as some reads appear to lock the session again.

会话已禁用 - 任何读取或写入会话的尝试都会引发异常.

Session disabled - any attempt to read or write to the session throws an exception.

但是,使用现代 MVC 应用程序时,我会同时发生很多 AJAX 事件 - 我不希望它们排在服务器上的队列中,但我确实希望它们能够写入会话.

However with a modern MVC app I have lots of AJAX events happening at once - I don't want them the queue on the server but I do want them to be able to write to the session.

我想要的是第四种模式:脏读,最后写胜

What I want is a fourth mode: Dirty read, last write wins

我认为(很高兴得到纠正)唯一的方法是完全替换 ASP.Net 的会话.我可以编写我的自己的提供程序,但 ASP 仍会调用它它支持的 3 种模式之一.有没有办法让ASP.Net支持乐观并发?

I think (happy to be corrected) that the only way to do this is to completely replace ASP.Net's sessions. I can write my own provider, but ASP will still call it with one of the 3 patters it supports. Is there any way to make ASP.Net support optimistic concurrency?

这让我用一个新类替换了对会话的所有调用,该类基本上做同样的事情,但不锁定 - 这很痛苦.

This leaves me replacing all calls to the session with a new class that basically does the same thing, but doesn't lock - which is a pain.

我希望尽可能多地保留当前会话的内容(最重要的是各种日志中的会话 ID),并且代码替换量最少.有没有办法做到这一点?理想情况下,我希望 HttpContext.Current.Session 指向我的新类,但没有 ASP.Net 锁定任何请求.

I want to keep as much of the current session stuff as I can (most significantly session IDs in various logs) with the minimum amount of code replacement. Is there any way to do this? Ideally I'd want HttpContext.Current.Session to point to my new class but without ASP.Net locking any requests.

有没有人做过这样的事情?对于所有 AJAXey MVC 应用程序来说,这是 ASP 的一个新问题,这似乎很奇怪.

Has anyone already done something like this? It seems odd that with all the AJAXey MVC apps out there this is a new problem with ASP.

推荐答案

首先我说 MS asp.net 已经锁定了asp.net 处理页面"会话的核心,在webengine4.dll" 用于 asp.net 4 的 dll

First of all I say that MS asp.net have lock in the core of "asp.net processing a page" the session, somewhere in the "webengine4.dll" dll for asp.net 4

而且我说,从 MS asp.net 的角度来看是正确的并以这种方式锁定会话 因为 asp.net 无法知道我们在会话中保留什么类型的信息,因此可以制作一个正确的最后一次写入获胜".

And I say that from the view point of MS asp.net act correct and lock the session this way because asp.net can not know what type of information we keep on session so can make a correct "last write wins".

同样正确的是锁定会话整页,因为这样可以为您的程序提供非常重要的同步,根据经验,现在我说您需要它对于您的大部分操作.用我的会话替换 ms 会话后,我需要对所有操作进行全局锁定,否则我会遇到双重插入、双重操作等问题.

Also correct is lock for the session the full page because that way is gives your a very important synchronizations of your program, that from experience now I say you need it for most of your actions. After I have replace the ms session with mine, on all of my actions I need to make global lock, or else I have problems with double inserts, double actions, etc.

我将在此处举个例子,说明我在此处认识到的问题.会话数据保存在 SessionSateItemCollection 上,它是一个键列表.当 session 读取或写入这个集合时,它们一起做.所以让我们看看这个案例.

I give an example of the issue that I recognize here. Session data are saved on SessionSateItemCollection that is a list of keys. When session reads or write this collection is do it all of them together. So let see this case.

我们在会话中有树变量,VAR1"、VAR2"、VAR3"

we have tree variables on session, "VAR1", "VAR2", "VAR3"

第 1 页.
getsession(实际获取所有数据并将它们放在列表中)
session[VAR1] = "data1";
保存会话()
结果是 VAR1=data1, VAR2=(var2 的最后一个数据), VAR3=(var3 的最后一个数据)

Page 1.
getsession (actually get all data and place them on list)
session[VAR1] = "data1";
savesession()
result is VAR1=data1, VAR2=(last data of var2), VAR3=(last data of var3)

第 2 页.
getsession(实际获取所有数据并将它们放在列表中)
session[VAR2] = "data2";
保存会话()
结果是 VAR1=(var1 的最后一个数据), VAR2=data2, VAR3=(var3 的最后一个数据)

Page 2.
getsession (actually get all data and place them on list)
session[VAR2] = "data2";
savesession()
result is VAR1=(last data of var1), VAR2=data2, VAR3=(last data of var3)

第 3 页.
getsession(实际获取所有数据并将它们放在列表中)
session[VAR3] = "data3";
保存会话()
结果是 VAR1=(var1 的最后一个数据), VAR2=(var2 的最后一个数据) VAR3="data3"

Page 3.
getsession (actually get all data and place them on list)
session[VAR3] = "data3";
savesession()
result is VAR1=(last data of var1), VAR2=(last data of var2) VAR3="data3"

注意这里每个页面都有一个数据的副本,因为他从会话介质中读取它们(例如,当它们上次从数据库中读取时)

Note here that each page have a clone of the data, as he read them from the session medium (eg as they last readed from database)

如果我们让这 3 个页面在没有锁定的情况下运行,我们实际上没有脏读,也没有最后一次写入获胜" - 我们这里有的是最后一次写入破坏其他页面",因为如果你再想一想,当 VAR1 改变时,为什么 VAR2 和 VAR3 保持不变?如果您在其他地方更改了 VAR2 会怎样.

If we let this 3 pages run with out locking, we do not have actually dirty read, nether "last write wins" - What we have here is "the last write destroy the others", because if you think it again, when VAR1 change, why the VAR2 and VAR3 stay the same ? what if you have change VAR2 somewhere else.

出于这个原因,我们不能在没有锁定的情况下放任这种情况.

and for that reason we can not let this with out lock as it is.

现在用 20 个变量来想象……完全一团糟.

And now imaging that with 20 variables... totally mess.

由于asp.net的多线程的多池,跨池、跨计算机保持相同数据的唯一方法就是拥有一个通用的数据库,或者像asp.net State Service这样的所有进程通用的程序.

Because of the multithread of asp.net of many pools, the only way to keep the same data across pools, and across computers is to have a common database, or a common to all process program like the asp.net State Service.

我选择拥有一个通用数据库比为该提议创建程序更容易.

I select to have a common database as more easy than create a program for that propose.

现在,如果我们连接我们制作的 cookie连接到用户和会话的数据用户,我们使用完全自定义的数据库字段控制数据我们知道我们喜欢锁定什么,不喜欢什么,如何保存或更改,或比较和保留上次写入的获胜数据,我们可以完成这项工作,并完全禁用 asp.net 会话,这是为所有人制作的通用会话保持器需要,但不是为了处理这种特殊情况.

Now if we connect a cookie that we make, to the user to the data user of the session, and we control the data using a totally custom database field that we know what we like to lock, what not, how to save or change, or compare and keep the last write wins data, we can make this work, and totally disable the asp.net session that is a generic session keeper made for all needs, but not made to handle special cases like this one.

asp.net 能否在未来的版本中实现这一点,是的,他可以通过创建一个名为dirty 的额外字段,并在会话中保存数据,使用dirty 字段或类似的东西合并数据,但是可以不要让它现在正常工作 - 至少从我发现到现在为止.
实际上 SessionStateItem 在属性上有一个脏标志,但没有在保存数据结束时进行合并.如果其他人想解决现有的 ms asp.net 会话状态保持器,我真的会很高兴,我写了到目前为止我发现的内容,但这并不意味着肯定没有办法 - 我没有找到了它.

Can asp.net make this work on the future release, yes he can by making an extra field called dirty, and on the session save data, make a merge of data using the dirty field, or something like that, but can not make this now work as it is - at least from what I have found until now.
Actually SessionStateItem have a dirty flag on properties, but did not make this merge on the end of save data. I will really love if some one else think for a solution to the existing ms asp.net session state keeper, I am write what I have found up to now, but this is not mean that for sure there is no way - I have not found it as it is.

希望对大家有帮助:)

在这个答案中https://stackoverflow.com/a/3660837/159270 詹姆斯写了一个自定义模块之后说:我仍然无法相信 ASP.Net Session 的自定义实现会锁定整个请求的会话.

in this answer https://stackoverflow.com/a/3660837/159270 the James after write a custom module says: I still can't believe the custom implementation of ASP.Net Session locks the session for the whole request.

这篇关于完全替换 ASP.Net 的会话的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆