asp.net-mvc MVC 中是否有最佳实践和推荐的 Session 变量替代方案
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23419011/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a best practice and recommended alternative to Session variables in MVC
提问by Mark
Okay, so first off before anyone attempts to make a determination that this is a "duplicate" question; I have reviewed most of the posts on SO regarding similar questions but even in combination of all that has been said I still am somewhat at a dilemma as to the definitive or maybe I should say unanimous agreement on this.
好的,首先,在任何人试图确定这是一个“重复”问题之前;我已经了关于类似问题的大多数关于 SO 的帖子,但即使结合所有已经说过的内容,我仍然在确定性方面处于两难境地,或者我应该对此表示一致同意。
I can however say that I have (based on the posts) conclusively determined that the answer is based on the scope of the requirement. But even with consideration of this, the opinions seem too diverse for me to make a decision as to how I should handle this.
但是,我可以说我(基于帖子)最终确定答案是基于要求的范围。但即使考虑到这一点,意见似乎也太多样化了,我无法决定我应该如何处理。
My immediate requirement is that I need to persist variable data from 1 controller across many views. More specifically, I have a controller and corresponding view that handles shopping cart item counts and I would like to persist that data across multiple views. I am thinking that the _layout view is the most logical choice for this.
我的直接要求是我需要在多个视图中保存来自 1 个控制器的变量数据。更具体地说,我有一个控制器和相应的视图来处理购物车项目计数,我想在多个视图中保留该数据。我认为 _layout 视图是最合乎逻辑的选择。
Now I have successfully accomplished this task by assigning the value to a Session variable which is retrieved from my _layout view; so even when the user were to navigate any where within the site the number of items in the Shopping Cart will persist until either they leave the site or complete the checkout; in which case the variable will be cleared in code.
现在我通过将值分配给从我的 _layout 视图中检索的 Session 变量成功地完成了这项任务;因此,即使用户要浏览网站内的任何位置,购物车中的商品数量也会一直存在,直到他们离开网站或完成结帐;在这种情况下,变量将在代码中被清除。
The posts I've read seemed biased to either staying away from Session variables in favor of Cookies and storing data in a database; or stating that for the intent purpose for which I propose to use them, Session variables are perfectly fine to use.
我读过的帖子似乎偏向于远离 Session 变量而支持 Cookies 并将数据存储在数据库中;或者说出于我建议使用它们的目的,会话变量非常适合使用。
The other thing I've read suggests that Session variables can potentially impede overall performance if there is high traffic on the site since the information is stored on the server.
我读过的另一件事表明,如果站点上的流量很高,由于信息存储在服务器上,会话变量可能会影响整体性能。
I personally cannot justify storing this type of information in a database and subsequently hitting the database as I'd imagine that this could also affect site performance and seems a bit overkill for storage of temporary data. TempData, ViewData and ViewBag do not work in persisting the data so they are not logical choices for the requirement IMO.
我个人无法证明将此类信息存储在数据库中并随后访问数据库是合理的,因为我认为这也会影响站点性能,并且对于存储临时数据似乎有点矫枉过正。TempData、ViewData 和 ViewBag 在持久化数据方面不起作用,因此它们不是 IMO 要求的逻辑选择。
If there is another well suited alternative to the Session variable (which is working for me) I would like to know what it is.
如果有另一个非常合适的 Session 变量替代品(对我有用),我想知道它是什么。
2 posts that seem contradictory in effort of providing best recommendations leave me a bit confused.
2 个在提供最佳建议方面似乎相互矛盾的帖子让我有点困惑。
Cons: Is it a good practice to avoid using Session State in ASP.NET MVC? If yes, why and how?
缺点:避免在 ASP.NET MVC 中使用会话状态是一个好习惯吗?如果是,为什么以及如何?
优点:仍然可以在 ASP.NET mvc 中使用 Session 变量,或者对于某些东西(例如购物车)是否有更好的选择
Seems that this question (although presented in many different variations) has no definitive answer that I can conclude.
似乎这个问题(尽管有许多不同的变体)没有我可以得出结论的明确答案。
If there is a more preferrable way to accomplish this without overkill then that is the answer I'm in search of.
如果有更可取的方法来实现这一点而不会矫枉过正,那么这就是我正在寻找的答案。
I read somewhere the use of MVC filters in tandem with the Global.ascx application start section as well, but this does not seem appropriate for variables set at the controller level as much as perhaps, static variables.
我在某处阅读了 MVC 过滤器的使用以及 Global.ascx 应用程序启动部分,但这似乎不适用于在控制器级别设置的变量,而不是静态变量。
Can someone maybe squash (for lack of a better word) the many diverse opinions on the topic and maybe provide a more definitive answer to the question? I'm sure the diverse opinions have their place and I'm not attempting to discredit them. But having a definitive and possibly unanimous answer would be better; then I could sort through the other posts to determine what is best for my application.
有人可能会压制(因为没有更好的词)关于该主题的许多不同意见,并可能为该问题提供更明确的答案?我相信不同的意见都有其一席之地,我并不试图诋毁他们。但是有一个明确的、可能是一致的答案会更好;然后我可以对其他帖子进行分类,以确定最适合我的应用程序的内容。
Of course, if this question has no definitive answer; just tell me that and I'll attempt to derive my own answer from the other posts.
当然,如果这个问题没有确定的答案;告诉我,我会尝试从其他帖子中得出我自己的答案。
Thanks
谢谢
===========================================================
================================================== ==========
UPDATED RESPONSE TO ANSWERS PROVIDED
对所提供答案的更新回复
Caching and Cookies seem to be a general preference from the responses however I've also noted the statement that caching its not an ideal candidate to use across multiple web server because synchronization can be a potential issue.
缓存和 Cookie 似乎是响应中的普遍偏好,但是我也注意到缓存不是跨多个 Web 服务器使用的理想选择,因为同步可能是一个潜在的问题。
Giving credit to Tim, it's stated that Database storage is optimized and users have the option to return at a later time and continue where they left off.
值得称赞的是 Tim,据说数据库存储已经过优化,用户可以选择稍后返回并从上次中断的地方继续。
That is an excellent point, but keeping foresight on probabilities; its likely a reasonable given that some users may not return leaving unneccessary data in the database.
这是一个很好的观点,但要对概率保持远见;鉴于某些用户可能不会返回而在数据库中留下不必要的数据,这可能是合理的。
So keeping the DB optimized and clean (which "to me" is of equal relevance) would require implementing a maintenance task to automatically expire those records based on a set threshold of time to account for those circumstances. Although a maintenance task is not an unquestionable option, I still think this adds just a bit more work to the task simply for the intent purpose of serving as temporary storage.
因此,保持数据库优化和清洁(“对我来说”同样重要)需要实施维护任务,以根据设定的时间阈值自动使这些记录过期,以解决这些情况。虽然维护任务不是一个毫无疑问的选择,但我仍然认为这只是为了作为临时存储的目的而为任务增加了更多的工作。
Nonetheless, I do respect Tim's recommendation and believe it deserves merit on countering my initial opinion to a degree; that a database would not seem to be a viable option for storing Temporary data; so I think the compromise would be to store the data in a database (given the scenario of a Shopping Cart or similar) perhaps after a checkout. This way as you previously stated, the data may be persistently tracked upon subsequent visits so you have a record of transactions. But more importantly, it would be data of those transactions having real relevance to persist to the database.
尽管如此,我确实尊重蒂姆的建议,并相信在一定程度上反驳我最初的意见是值得的;数据库似乎不是存储临时数据的可行选择;所以我认为妥协是在结账后将数据存储在数据库中(考虑到购物车或类似的场景)。通过这种方式,如您之前所述,后续访问时可能会持续跟踪数据,以便您拥有交易记录。但更重要的是,那些具有真正相关性的交易数据才能持久保存到数据库中。
It was also stated that although Session is faster than Database; but notwithstanding to have its caveats that can to some degree be mitigated by other mechanisms such as leveraging the SessionStateBehavior attribute, just serving as one example.
还有人说虽然Session比Database快;但尽管有其警告,在某种程度上可以通过其他机制(例如利用 SessionStateBehavior 属性)来缓解,仅作为一个示例。
BUT... I think Erik kind of drove the point home with the Dunning-Kruger Effect. Although, from the content and explanations for proposed answers given here; I seriously doubt the expertise of any of the individuals who have responded is any way questionable. Nonetheless, I tend to agree on the fact of getting a unanimous opinion may be somewhat of a higher than reasonable expectation on my part.
但是......我认为埃里克通过邓宁 - 克鲁格效应将这一点带回家。虽然,从这里给出的建议答案的内容和解释;我严重怀疑任何做出回应的人的专业知识是否有任何问题。尽管如此,我倾向于同意这样一个事实,即获得一致意见可能比我的合理预期要高一些。
What I was more specifically looking for was a general consensus for a technique that would comfortably accomodate a diverse number of scenarios. In other words, something that would accomodate not only my particular scenario but also provide the element of scalability to larger environments with potentially heavier traffic. This way a change in the programming would be either alleviated altogether or minimal at best.
我更具体地寻找的是对一种可以轻松适应多种场景的技术的普遍共识。换句话说,这不仅可以适应我的特定场景,而且还可以为具有潜在更重流量的更大环境提供可扩展性元素。这样,编程中的更改要么完全缓解,要么充其量最小。
==================================================
==================================================
Summary based on the feedback:
根据反馈总结:
Session variables seem to accomodate smaller case scenarios and when applicable, but they have some potential for persistence concerns among other notable discrepancies as stated very thorougly by Erik. So this option obviously will not fit a scalable model.
Caching is preferable over Session variables but again not neccessarily the "best" scalable option due to among other things to the potential synchronization complexities in web server farm environments as previously pointed out. But an option nonetheless.
Database storage is scalable but for the intent purpose of temporary volatile storage is probably not the most elegant option from a database perspective as it would require periodical cleanup. Personally, having a strong foundation in database concepts earlier in my career this probably is not going to be something that many developers will likely agree with; but using the database for this purpose may suffice for Web Development from a programmers perspective; however from perspective of the DAL and DB development this (to me) has the potential for mandating an additional DB task to enforce an efficient backend.
Cookies seem to be a nice option having the combined "desirable" elements of Session variables and caching.
会话变量似乎适用于较小的案例场景,并且在适用时,但它们有一些潜在的持久性问题以及 Erik 非常详尽地陈述的其他显着差异。所以这个选项显然不适合可扩展的模型。
缓存比 Session 变量更可取,但也不一定是“最佳”可扩展选项,因为除其他外,如前所述,Web 服务器群环境中潜在的同步复杂性。但仍然是一个选择。
数据库存储是可扩展的,但出于临时易失性存储的目的,从数据库的角度来看可能不是最优雅的选择,因为它需要定期清理。就我个人而言,在我职业生涯的早期拥有扎实的数据库概念基础,这可能不会得到许多开发人员的同意。但从程序员的角度来看,为此目的使用数据库可能足以满足 Web 开发的需求;然而,从 DAL 和 DB 开发的角度来看,这(对我来说)有可能要求额外的 DB 任务来强制执行高效的后端。
Cookie 似乎是一个不错的选择,它结合了 Session 变量和缓存的“理想”元素。
==================================================
==================================================
CONCLUSION
结论
Based on the answers; I think COOKIES and CACHING seem to be generally well rounded proposals for best practice across the board in combination with database storage when continued persistence is required after the fact; as potentially good candidates for scalability of the ones presented.
根据答案;当事后需要持续持久性时,我认为 COOKIES 和 CACHING 似乎通常是全面的最佳实践建议,结合数据库存储;作为所呈现的可扩展性的潜在良好候选者。
The ultimate choice between the 2 would seem to be based on the amount and type of data requiring storage (e.g. sensitive vs non-sensitive and whether or not there is any concern that the client may alter the data on their end); in addition to special considerations for COOKIES in the fact that they may be disabled by the clients.
两者之间的最终选择似乎是基于需要存储的数据的数量和类型(例如,敏感与非敏感以及是否担心客户端可能会更改其最终数据);除了对 COOKIES 的特殊考虑之外,它们可能会被客户禁用。
Obviously, there is no one size fits all solution as clearly pointed out and concluded from the answers provided but in terms of scalability; I may be wrong but these seem to be the BEST choices available.
显然,根据所提供的答案明确指出并得出结论,但在可扩展性方面,没有一种适用于所有情况的解决方案;我可能错了,但这些似乎是可用的最佳选择。
Because all the responses are good; I'm fairly going to credit all the posts as useful and going to accept Erik's answer as a well rounded overall scalable solution. I wish I could select more than one accepted answer as I believe Tim's response was also very well layed out and concise.
因为所有的反应都很好;我相当相信所有帖子都很有用,并会接受 Erik 的回答,认为这是一个全面的整体可扩展解决方案。我希望我可以选择多个已接受的答案,因为我相信 Tim 的回答也非常简洁明了。
Gupta's response was good also, but I wanted more elaboration of the proposed answer and not a repeat of previous posts.
Gupta 的回应也很好,但我想要对提议的答案进行更多详细说明,而不是重复以前的帖子。
Thanks Guys!
谢谢你们!
采纳答案by Erik Funkenbusch
You will never get unanimous opinion on anything in any large group of people. That's just human nature. Part of that stems from the Dunning-Kruger Effectwhich states that the less someone knows about a subject, the more likely they are to over value their expertise in that subject. In other words, lots of people think they know something, but only because they don't know they don't know it. Part of it is simply that people have different experiences, and some have found no problems with session, while others have in various situations, or vice versa...
在任何一大群人中,您永远不会对任何事情达成一致意见。这只是人的本性。部分原因源于邓宁-克鲁格效应,该效应表明,某人对某个主题了解得越少,他们就越有可能高估自己在该主题上的专业知识。换句话说,很多人认为他们知道某事,但只是因为他们不知道他们不知道。部分原因只是人们有不同的体验,有些人发现 session 没有问题,而其他人则在各种情况下都有,反之亦然......
So, to backup your research, which suggest that the answer depends heavily on the requirements, we need to understand what your requirements are. If this is to be a high traffic site, with load balanced servers in a web farm, then stay as far away from session as you can. Sure, it's possible to share session in various ways in a server farm environment (session server, distribute cache server, etc..), but avoiding session will almost always be faster if you can help it.
因此,为了支持您的研究,这表明答案在很大程度上取决于需求,我们需要了解您的需求是什么。如果这是一个高流量站点,并且在 Web 场中具有负载平衡的服务器,那么请尽可能远离会话。当然,可以在服务器场环境(会话服务器、分发缓存服务器等)中以各种方式共享会话,但是如果您可以提供帮助,避免会话几乎总是更快。
If your site is a single server, and unlikely to ever grow beyond that. And your traffic patterns are relatively low, then session may be a useful option. However, you should always be aware that session is unreliable storage, and can disappear on you at any time. If the app pool is recycled, session is gone. If an uncaught exception bubbles up to the worker process, the session may be gone. If IIS thinks there's not enough memory, your session may be gone, regardless of any timeout values configured. You also can't always get reliable notification that a session has ended, since terminated sessions do not fire the Session_End event.
如果您的站点是单个服务器,并且不太可能超出此范围。并且您的流量模式相对较低,那么会话可能是一个有用的选择。但是,您应该始终意识到会话是不可靠的存储,并且随时可能消失。如果应用程序池被回收,会话就会消失。如果一个未捕获的异常冒泡到工作进程,会话可能会消失。如果 IIS 认为没有足够的内存,则无论配置了任何超时值,您的会话都可能会消失。您也无法始终获得会话已结束的可靠通知,因为终止的会话不会触发 Session_End 事件。
Another issue is that Session is serialized. In other words, IIS prevents more than one thread from writing to the session at a time, and it often does this by locking the session while a thread is running if it has not opted out of writable session locking. This can cause severe problems in some cases, and merely poor performance in others. You can mitigate this by marking various methods with a read-only session attribute if you aren't going to be modifying it in that method.
另一个问题是 Session 是序列化的。换句话说,IIS 防止多个线程一次写入会话,并且它通常通过在线程运行时锁定会话(如果它没有选择退出可写会话锁定)来做到这一点。这在某些情况下会导致严重的问题,而在其他情况下只会导致性能不佳。如果您不打算在该方法中修改它,您可以通过使用只读会话属性标记各种方法来缓解这种情况。
Ultimately, if you do choose to use session, then try to only use it for small, short lived things if at all possible, and if not possible then build in a way to "regenerate" the data if the session is lost. For instance, using your number of items in cart example, you could write a method that first checks to see if the value is there, and if not it goes out and loads it from the database. Always use this method to access the variable, rather than accessing it directly from session... this way, if the session is lost it will just reload it.
最终,如果您确实选择使用会话,那么如果可能的话,尝试仅将其用于小的、短暂的事物,如果不可能,则在会话丢失时以“重新生成”数据的方式构建。例如,使用购物车中的商品数量示例,您可以编写一个方法,首先检查该值是否存在,如果不存在,则退出并从数据库中加载它。始终使用此方法访问变量,而不是直接从会话访问它...这样,如果会话丢失,它只会重新加载它。
However, having said this... For the number of items in a cart, I would generally prefer to use a cookie for this information, since cookies get passed to the page on every load anyways, and this is a small discrete unit of data. Generally prefer Session for sensitive data that you want to prevent the user from being able to change.. number of items in the cart simply doesn't fit that rule.
但是,话虽如此......对于购物车中的物品数量,我通常更喜欢使用 cookie 来获取此信息,因为无论如何 cookie 都会在每次加载时传递到页面,这是一个小的离散数据单元. 对于您希望防止用户更改的敏感数据,通常更喜欢使用 Session。购物车中的商品数量根本不符合该规则。
回答by Tim Medora
When
什么时候
Databases are highly optimized. A simple value like a shopping cart count is a good candidate for caching by the database and (hopefully) cheap to compute outright. It may be a non-issue.
数据库高度优化。像购物车计数这样的简单值很适合由数据库缓存,并且(希望)可以便宜地直接计算。这可能不是问题。
However, if you have ruled out other mechanisms, small, user-by-user values are viable candidates for session.
但是,如果您排除了其他机制,那么小的、逐个用户的值是会话的可行候选者。
Cacheis fine for site-wide values, or user-specific values with unique keys. However, synchronizing caches across multiple web servers can be difficult. Out of process session state will stay synchronized because it is stored in a single location (database or a state server).
Cache适用于站点范围的值或具有唯一键的特定于用户的值。但是,跨多个 Web 服务器同步缓存可能很困难。进程外会话状态将保持同步,因为它存储在单个位置(数据库或状态服务器)。
Of course, there are many 3rd party caching alternatives with various options to keep them synchronized.
当然,有许多 3rd 方缓存替代方案,其中包含各种选项以保持同步。
Regardless of where the count is temporarily stored, I'm of the opinion that shopping carts themselves should be stored in the database so that users have the option to return later and continue where they left off.
无论计数临时存储在哪里,我都认为购物车本身应该存储在数据库中,以便用户可以选择稍后返回并从上次停止的地方继续。
Performance
表现
If you use out of process session state (e.g. in a load balanced environment and/or to make session more durable), it willhit a database or call an out of process service, but the call is relatively cheap unless you are serializing large object graphs.
如果你使用了进程外会话状态(例如在负载平衡环境和/或使会议更耐用),这将创下一个数据库或拨打了过程的服务,但电话是相对便宜的,除非你是序列化大对象图表。
Session is loaded once per request. Subsequent read access is very fast.
每个请求加载一次会话。随后的读取访问非常快。
Writing to session can be detrimental to performance, even when there is no load. Why? most modern applications use asynchronous calls, and when multiple async calls hit an HTTP handler (page, controller, etc) that reads/writes session, ASP.Net will lock the session to serialize access. To avoid this, you can decorate your controllers with [SessionState( SessionStateBehavior.ReadOnly )]
写入会话可能对性能有害,即使在没有负载的情况下也是如此。为什么?大多数现代应用程序使用异步调用,并且当多个异步调用命中读取/写入会话的 HTTP 处理程序(页面、控制器等)时,ASP.Net 将锁定会话以序列化访问。为了避免这种情况,你可以用[SessionState( SessionStateBehavior.ReadOnly )]
Design
设计
Now I have successfully accomplished this task by assigning the value to a Session variable which is retrieved from my _layout view;
现在我通过将值分配给从我的 _layout 视图中检索的 Session 变量成功地完成了这项任务;
This seems like mixing concerns, i.e. having the view aware of the underlying storage mechanism. From a purist standpoint, I would set this value on a view model or at least put it in the ViewBag. From a practical standpoint, one or two values retrieved in this manner probably won't hurt anything, but beware of letting it grow much further.
这似乎是混合关注点,即让视图了解底层存储机制。从纯粹主义者的角度来看,我会在视图模型上设置这个值,或者至少把它放在ViewBag. 从实际的角度来看,以这种方式检索的一两个值可能不会造成任何伤害,但要小心让它进一步增长。
I read somewhere the use of MVC filters in tandem with the Global.ascx application start section as well, but this does not seem appropriate for variables set at the controller level as much as perhaps, static variables.
我在某处阅读了 MVC 过滤器的使用以及 Global.ascx 应用程序启动部分,但这似乎不适用于在控制器级别设置的变量,而不是静态变量。
Static variables have perfectly legitimate uses, but you must understand them thoroughly or risk serious problems.
静态变量具有完全合法的用途,但您必须彻底了解它们,否则可能会出现严重问题。
See my answers pertaining to static variables in ASP.Net:
请参阅我关于 ASP.Net 中的静态变量的答案:
回答by Anirudha Gupta
Session alternative in different prospective :-
不同前景中的会话替代方案:-
When you keep something in session it breaks the primary rule in ASP.NET MVC. You can use these options as an alternative of session.
当您在会话中保留某些内容时,它会破坏 ASP.NET MVC 中的主要规则。您可以使用这些选项作为会话的替代方案。
If your asp.net (MVC) session do boxing unboxing on the object then it makes a little load on the server. Try this idea
如果您的 asp.net (MVC) 会话在对象上进行装箱拆箱,那么它会给服务器带来一些负载。试试这个主意
Caching :- Storing a List or something like large data in session is better can fit in Caching. You have control on whenever you want it to expire rather than user session.
If your app depends on JSON/Ajax data then you can use some kind of functionality provided in html5 (like WebSQL, IndexDB). it will not use the cookie so you can save some workload on the server.
缓存:-在会话中存储列表或诸如大数据之类的东西更适合缓存。您可以控制它何时过期,而不是用户会话。
如果您的应用程序依赖于 JSON/Ajax 数据,那么您可以使用 html5 中提供的某种功能(如 WebSQL、IndexDB)。它不会使用 cookie,因此您可以在服务器上节省一些工作量。

