gpt4 book ai didi

asp.net - ASP.NET session 对象中的 Entity Framework 对象上下文?

转载 作者:行者123 更新时间:2023-12-03 15:08:28 25 4
gpt4 key购买 nike

我们有一个多层的Asp.NET Web窗体应用程序。数据层具有一个称为DataAccess的类,该类会影响IDisposable,并将 Entity Framework 对象上下文的实例作为私有(private)字段。该类具有许多返回各种Entities集合的公共(public)方法,并将在处理它的对象上下文时对其进行处理。

由于我们遇到了许多问题,我们决定将对象上下文(或DataAccess的实例)在服务器上的作用域保持更长的时间是一个很大的好处。建议将一个实例保留在this postHttpContext.Current.Items集合中,以便每个Http请求具有一个实例。

我想知道的是:将对象上下文的实例存储在HttpContext.Current.Session对象中会引起什么问题/关注/问题???

  • 我假设Session对象已完成并在用户 session 期满时设置为垃圾回收,因此该实例将被正确处理。
  • 我假设大多数默认浏览器设置都将使我们的应用程序将其SessionId cookie置于无限制状态。
  • 关于随时间进行缓存和相对较少的并发用户而言,对象上下文将要处理的数据量不是很大,并且不会对我们的体面服务器硬件造成问题。

  • 这将实现相对较快,并且不会影响我们许多现有的单元测试。

    我们将使用AutoFac和ServiceProvider类来提供实例。当需要ObjectContext的实例时,它将由类似于以下代码的代码返回:
    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];
    }

    干杯。

    最佳答案

    在 session 状态下存储ObjectContext并不是一种好习惯,因为该类旨在封装工作单元模式-您加载一些数据(实体),对其进行修改,然后提交更改(被UOW跟踪),然后就完成了。 UOW对象不是旨在或设计为长期存在的。

    就是说,可以做到这一点而不会引起任何重大灾难,您只需要确保您了解幕后发生的事情即可。 如果您打算这样做,请阅读,以使您知道自己要进入的领域并了解其取舍。

    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.



    这实际上是不准确的,或者至少似乎是基于其措辞的方式。 session 到期/注销不会立即导致任何项目被处置。它们最终将被最终确定/处置,但这取决于垃圾收集器,您无法控制何时发生。这里最大的潜在问题是,如果您碰巧手动打开 ObjectContext上的连接,该连接将不会自动关闭-如果您不小心,则可能最终导致数据库连接泄漏,而常规连接不会发现这种连接单元测试/集成测试/实时测试。

    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没有自己的内部“垃圾收集”,它不会清除已经很长时间没有使用的缓存/跟踪的实体。如果您确定基于用例不会出现问题,那么可以,但是主要困扰您的是您对情况缺乏控制。

    另一个问题是线程安全性。 ObjectContext不是线程安全的。 session 访问通常是序列化的,因此一个请求将阻塞等待其 session 状态,直到对同一 session 的另一个请求完成为止。但是,如果以后有人决定进行优化,尤其是页面级只读 session 的​​优化,则请求将不再拥有排他锁,并且您可能最终会遇到各种竞争条件或重新进入问题。

    最后但并非最不重要的当然是多用户并发问题。 ObjectContext永远永久地缓存其实体,直到将其处置为止。如果另一个用户在自己的 ObjectContext上更改了相同的实体,则第一个 ObjectContext的所有者将永远不会发现该更改。这些陈旧的数据问题很难调试,因为您实际上可以看到查询进入数据库并返回新数据,但是 ObjectContext会用缓存中已经存在的旧的陈旧数据覆盖它。我认为,这可能是避免使用长寿的 ObjectContext实例的最重要原因;即使您认为已对其进行了编码以从数据库中获取最新数据, ObjectContext仍将决定它比您更聪明,并且将您交给旧实体。

    如果您知道所有这些问题并已采取措施缓解这些问题,那就很好。但是我的问题是,为什么您真的认为 session 级 ObjectContext是一个好主意?创建 ObjectContext确实是非常便宜的操作,因为元数据已为整个AppDomain缓存。我猜想是您要么误以为它是昂贵的,要么是您试图在多个不同的网页上实现复杂的有状态过程,而后者的长期后果远比任何特定的情况都要糟糕。只需将 ObjectContext放入 session 中可能会对您造成伤害。

    如果您要继续进行下去,请确保您出于正确的理由而这样做,因为这样做的理由不多。但是,正如我所说,这绝对有可能做到,并且您的应用不会因此而崩溃。

    更新-对于其他由于“同一 session 上的多个请求可能会导致线程安全问题”而拒绝投票的任何人,请阅读 ASP.NET Session State Overview文档的底部。序列化的不仅仅是 session 状态的单个访问;任何获取 session 的请求都将对 session 保留排他锁,直到整个请求完成后才释放该 session 。除了上面列出的一些优化之外,在默认配置中,不可能有两个同时请求持有对 ObjectContext的同一 session 本地实例的引用。

    由于上面列出的几种原因,我仍然不会在 session 状态中存储 ObjectContext,但是除非您将其设置为一个,否则它不是线程安全问题。

    关于asp.net - ASP.NET session 对象中的 Entity Framework 对象上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2383966/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com