在ASP.NET会话实体框架对象上下文对象? [英] Entity Framework Object Context in ASP.NET Session object?

查看:110
本文介绍了在ASP.NET会话实体框架对象上下文对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个多层次的Asp.NET Web窗体应用程序。数据层有一个叫做类数据访问这impements 的IDisposable 并有一个私人我们的实体框架对象上下文的一个实例领域。这个类有一些公共的方法返回实体各种收藏,它是处置时将出售其对象上下文。

We have a multi-layered Asp.NET Web Forms application. The data layer has a class called DataAccess which impements IDisposable and has an instance of our Entity Framework Object Context as a private field. The class has a number of public methods returning various collections of Entities and will dispose its Object Context when it is disposed.

由于一些我们一直面临的问题,我们决定这将是一大利好,以保持对象上下文(或数据访问的实例)的范围较长的服务器上。有人建议,以保持 HttpContext.Current.Items 集合中的一个实例从<一个href=\"http://dotnetslackers.com/articles/ado_net/managing-entity-framework-objectcontext-lifespan-and-scope-in-n-layered-asp-net-applications.aspx\"相对=nofollow>这个帖子为了让每个Http请求一个实例。

Due to a number of problems we've been facing, we decided it would be a big plus to keep the Object Context (or an instance of DataAccess) in scope for longer on the server. A suggestion was made to keep an instance in the HttpContext.Current.Items collection from this post in order to have one instance per Http request.

我想知道的是:从存储我们在 HttpContext.Current.Session 目标对象上下文的实例会出现什么问题/顾虑/问题? ?

What I'm wondering is: What issues / concerns / problems would arise from storing an instance of our Object Context in the HttpContext.Current.Session object????


  • 我假设Session对象定稿,并在用户的会话过期垃圾收集设置,所以实例将被妥善处理。

  • 我假设大多数默认浏览器设置将让我们的应用程序将其的SessionID cookie的时候没有顾虑。

  • 对象上下文将处理的数据量不是很大,不会对我们的体面的服务器硬件问题,随着时间的推移关于缓存和相对较少的并发用户。

这会比较快速实施并不会影响我们的许多现有的单元测试。

This will be relatively quick to implement and will not affect our many existing unit tests.

我们将使用AutoFac和的ServiceProvider类提供实例。当需要的ObjectContext的一个实例,将通过与此类似code被返回:

We'll be using AutoFac and a ServiceProvider class to supply instances. When an instance of the ObjectContext is required it will be returned by code similar to this:

private static Entities GetEntities(IContext context)
{
    if (HttpContext.Current == null)
    {
        return new Entities();
    }

    if (HttpContext.Current.Session[entitiesKeyString] == null)
    {
        HttpContext.Current.Session[entitiesKeyString] = new Entities();
    }

    return (Entities)HttpContext.Current.Session[entitiesKeyString];
}

干杯。

推荐答案

存储一个的ObjectContext 中的会话状态是不是我会认为是因为一个很好的做法类用于封装单元的工作模式 - 你加载了一些数据(实体),进行修改,提交你的修改(这是由UOW跟踪),然后你用它做。 UOW对象不打算或设计为长寿命。

Storing an ObjectContext in the session state is not something I would consider to be a good practice since the class is intended to encapsulate a unit-of-work pattern - you load up some data (entities), modify them, commit your changes (which are tracked by the UOW), and then you're done with it. UOW objects are not intended or designed to be long-lived.

这就是说,它的可以的进行,而不会造成任何重大灾难​​做的,你只需要确保你明白这是怎么回事幕后。 请阅读如果你打算这样做,让你知道你得到自己陷入什么,都知道权衡的。

That said, it can be done without causing any major catastrophes, you just have to make sure you understand what's going on behind the scenes. Please read on if you plan on doing this so that you know what you're getting yourself into and are aware of the trade-offs.

我假设Session对象定稿并当用户的会话过期垃圾收集设置,所以实例将被妥善处理。

I'm assuming that the Session object is finalised and set for garbage collection when a user's session expires, so the instance will be disposed properly.

这实际上是不正确的,或至少似乎是基于它的措辞的方式。会话到期/注销不会立即引起任何的项目要设置。他们的最后的定稿/处置,但最多也就是垃圾回收器,你有它发生的时候无法控制。这里最大的潜在问题是,如果你碰巧手动打开的连接的ObjectContext ,这将不会被自动关闭 - 如果你不小心,你可能最终会泄漏的数据库连接,东西不会与普通的单元测试/集成测试/测试现场被发现。

This is actually inaccurate, or at least seems to be based on the way it's worded. Session expiry/logout will not immediately cause any of the items to be disposed. They will eventually be finalized/disposed but that is up to the garbage collector and you have no control over when it happens. The biggest potential problem here is if you happen to manually open a connection on the ObjectContext, which won't get closed automatically - if you're not careful, you could end up leaking database connections, something that wouldn't be uncovered with regular unit tests/integration tests/live tests.

对象上下文将处理的数据量不是很大,不会对我们的体面的服务器硬件问题,随着时间的推移关于缓存和相对较少的并发用户。

The amount of data the Object Context will be dealing with is not enormous and will not pose a problem for our decent server hardware, with regards to caching over time and relatively few concurrent users.

只要记住该增长是无限的。如果一个特定的用户决定使用你的网站全天运行不同的查询,连续12小时,然后在上下文会发展得越来越大。一个的ObjectContext 不拥有自己的内部的垃圾收集,它不清除那些没有被使用了很长一段时间的缓存/跟踪实体。如果你确定这不会根据您的使用案例再细的问题,而是应该困扰你的主要的事情是,你缺乏事实的控制的过度的情况。

Just keep in mind that the growth is unbounded. If a particular user decides to use your site for 12 straight hours running different queries all day then the context will just keep getting bigger and bigger. An ObjectContext doesn't have its own internal "garbage collection", it doesn't scavenge cached/tracked entities that haven't been used for a long time. If you're sure that this isn't going to be a problem based on your use cases then fine, but the main thing that should be bothering you is the fact that you lack control over the situation.

另一个问题是线程安全的。 的ObjectContext 不是线程安全的。会话访问通常被序列化,这样一个请求会阻塞等待它的会话状态,直到同一个会话的另一个请求已完成。但是,如果有人决定对优化以后,页级的专门优化只读会话,请求将不再持有一个独占锁,并有可能为你结了各种各样的竞争条件或重入问题

Another issue is thread-safety. ObjectContext is not thread-safe. Session access is normally serialized, so that one request will block waiting for its session state until another request for the same session is complete. However, if somebody decides to make optimizations later on, specifically the optimization of page-level read-only sessions, requests will no longer hold an exclusive lock and it would be possible for you to end up with various race conditions or re-entrancy problems.

最后但并非最不重要的是当然的多用户的并发问题。一个的ObjectContext 缓存的实体,直到永远,直到它被设置。如果另一个用户更改对自己同一实体的ObjectContext ,所有者的第一个的ObjectContext 将的从不的了解这种变化。这些过时的数据问题可以僵硬难以调试,因为你其实可以看查询到数据库回来新鲜的数据,但的ObjectContext 将与覆盖它旧的,过时的数据是已经在缓存中。这一点,在我看来,可能是为了避免长寿命的ObjectContext 情况下,最显著的原因;甚至当你认为你已经$ C $光盘,它从数据库中抓取的最新数据,在的ObjectContext 将决定它比你更聪明,交给你回老实体代替。

Last but not least is of course the issue of multi-user concurrency. An ObjectContext caches its entities forever and ever until it is disposed. If another user changes the same entities on his own ObjectContext, the owner of the first ObjectContext will never find out about that change. These stale data problems can be infuriatingly difficult to debug, because you can actually watch the query go to the database and come back with fresh data, but the ObjectContext will overwrite it with the old, stale data that's already in the cache. This, in my opinion, is probably the most significant reason to avoid long-lived ObjectContext instances; even when you think you've coded it to grab the most recent data from the database, the ObjectContext will decide that it's smarter than you and hand you back the old entities instead.

如果你意识到所有这些问题,并已采取措施,以减轻他们的罚款。但我的问题是,到底为什么你认为一个会话级的ObjectContext 是这样一个伟大的想法?创建的ObjectContext 真的是一个非常便宜的操作,因为元数据缓存为整个AppDomain中。我打赌猜测,要么你是错误的IM pression,它是昂贵的下面,或者你想在几个不同的网页执行复杂的状态的过程,而后者的长期后果是远比你可以通过简单地把一个的ObjectContext 到会话中做任何具体的危害加重。

If you're aware of all of these issues and have taken steps to mitigate them, fine. But my question would be, why exactly do you think that a session-level ObjectContext is such a great idea? Creating an ObjectContext is really a very cheap operation because the metadata is cached for the entire AppDomain. I'd wager a guess that either you're under the mistaken impression that it's expensive, or you're trying to implementing complicated stateful processes over several different web pages, and the long-term consequences of the latter are far worse than any specific harm you may do by simply putting an ObjectContext into the session.

如果你要继续做吧,只要确保你这样做是正确的原因,因为没有一大堆的理由这样做。但是,正如我所说,这是绝对有可能做的,您的应用程序不会炸毁结果。

If you're going to go ahead and do it anyway, just make sure you're doing it for the right reasons, because there aren't a whole lot of good reasons to do this. But, as I said, it's definitely possible to do, and your app is not going to blow up as a result.

更新 - 为别人考虑downvoting是因为同一会话的多个请求可能导致线程安全问题,请阅读的 ASP.NET会话状态概述文档。它不仅是个人访问的是序列化会话状态的;即获得一个会话的任​​何请求保留在未发布,直到整个请求完成会话独占锁。除外一些我上面列出的优化,这是不可能的默认配置那里永远是两家控股引用的的ObjectContext 同一会话的本地实例并发请求。

Update - for anyone else considering downvoting this because "multiple requests on the same session could cause thread-safety issues", please read the bottom of the ASP.NET Session State Overview documentation. It is not just individual accesses of the session state that are serialized; any request that acquires a session keeps an exclusive lock on the session that is not released until the entire request is complete. Excepting some of the optimizations I listed above, it is impossible in the default configuration for there to ever be two simultaneous requests holding references to the same session-local instance of an ObjectContext.

我仍然不会存储一个的ObjectContext 中几个上面列出的原因,会话状态,但它不是线程安全的问题,除非你能使之

I still wouldn't store an ObjectContext in the session state for several of the reasons listed above, but it is not a thread-safety issue unless you make it one.

这篇关于在ASP.NET会话实体框架对象上下文对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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