【问题标题】:session state variables and singleton class会话状态变量和单例类
【发布时间】:2012-04-11 23:07:27
【问题描述】:

我有一种情况,我需要从执行近半分钟的查询中检索数据并将其带到网页。 (没有办法减少这个时间,因为已经对其进行了最大量的优化) 我为我的应用程序使用四层架构以及实体框架(EF、数据访问层、业务逻辑层、UI)。 我正在尝试在创建 DAL 的实例时使用单例方法(DAL 反过来从数据库中检索数据),以便我能够重新使用此实例,因此可以额外使用不会在同一会话中创建实例。 如何设置会话状态并检查状态服务器中实例的可用性?

public static Singleton getInstance() {
     if (**instance == null**)
       instance = new Singleton();
     return instance;
   }

if 块中应该包含什么?我应该在if 块中检查什么条件?我真的不确定我必须做什么。

PS:此会话必须有 5 分钟的超时。我听说这可以在 Web.config 文件中指定。是真的吗?

【问题讨论】:

  • Session 是一个名称值集合。按名称获取 DAL 的实例,然后检查值是否为空。如果它不为空,则将其转换为 DAL 的实例。对于它的价值,我不会遵循这种模式。创建 DAL 的成本为何如此之高,以至于您希望避免为每个请求创建和处置实例?
  • 您是否为每个用户会话创建单独的 DAL?为什么 DAL 完全是特定于会话的?你不能只为 DAL 建立一个带有静态属性的工厂吗?调用该属性时,查看DAL实例的工厂静态成员是否为null。如果是,则实例化并返回。如果没有,请返回。
  • 你能发布有问题的 DAL 的内容吗?您想让实例保持活动状态这一事实可能会引发一些您应该注意的额外问题,例如保持连接打开等。
  • @krishna:每次创建 DAL 时都会触发存储过程?这似乎……很奇怪。通常,DAL 有助于代码调用数据库资源的能力,当应用程序还不需要它们时,它不应该在内部调用这些资源。另外,“我们希望数据不会在刷新时消失”是什么意思?听起来您想在会话(或任何其他状态管理方法)中管理数据本身,而不是 DAL 本身。听起来您正在为 每个 会话创建一个新的 DAL。所以每个用户都有自己的。这听起来也不对。
  • @krishna:我并不是要对您的代码过于挑剔,尤其是因为除了问题中非常小的 sn-p 之外,我们看不到您的任何代码。听起来您正在寻找建议以在已经存在缺陷的前提下继续进行。而且这个前提与我们其他人通常期望看到的存在严重脱节,因此我们无法真正制定一个连贯的答案。

标签: c# asp.net .net singleton session-state


【解决方案1】:

说实话,您应该使用实体框架上下文并在每次需要访问数据库时创建它,即在每个方法中。它被优化为以这种方式使用。连接池将确保每次重新创建 EF 上下文时不会受到惩罚。这是最佳做法。

但您的 DAL 可能不仅仅是简单的数据库访问。如果您想将它作为每个会话单独的单例,您必须在第一个请求时创建实例,将其存储到 Session 中并在使用前检查它是否存在。使用线程安全,代码可能如下所示:

class DALClass
{
    private static object instanceLock = new object();

    public static DALClass Instance
    {
        get
        {
            if (Session["DALInstance"] == null)
            {
                lock (instanceLock)
                {
                    if (Session["DALInstance"] == null)
                    {
                        Session["DALInstance"] = new DALClass();
                    }
                }
            }

            return (DALClass)Session["DALInstance"];
        }
    }
}

【讨论】:

  • 我不认为 DAL 对象应该是单例或缓存在会话中。缓存结果是,但不是做工作的对象。 DAL 最多应由 DI 处理并在每个 Web 请求上创建一次,请参阅城堡文档:stw.castleproject.org/…
  • 正如我在回答中指出的那样,在会话中使用 DAL 并不是最好的主意。除非我们不知道更多内容。
  • @Maciej :我将上下文放在会话中的实体中。可以吗?
  • @krishna,如果您的意思是实体框架上下文(从 ObjectContext 继承的类),那么您应该在每次需要使用它时在每个方法中创建它。不要将其视为新的数据库连接,因为它不是,而且创建起来相对便宜。
【解决方案2】:

在我看来,您的架构定义明确,适合依赖注入。使用 DI,您可以让您的 IOC 容器返回一个单例对象或瞬态对象。但是,在 Web 环境中使用单例时要非常小心,因为它们通常会带来比其价值更多的麻烦。

如果您正在运行的查询包含用户特定的数据,那么如果您使用的是控制器中的 MVC 之类的模式,我可能会将该查询的结果放入构成应用程序 UI 部分的代码中的会话中或演示者中的 MVP。

如果没有使用这些模式,那么您可以考虑将信息放入业务层内的会话中,但前提是您包装会话并将该依赖项注入到您的业务对象中,例如类似“IUserSession”的东西。业务项目不应包含对“system.Web”或类似内容的引用。

【讨论】:

  • 这里的关键点是查询的结果(不是 DAL)应该进入会话。 Session 对象本身已经具有您想要的所有特征:“不会在同一会话中创建其他实例。” (此外,如果您将查询发布在带有 SQL 标记的问题中,您可能会在优化它方面获得一些帮助。对于网页来说,30 秒太长了,除非您的用户别无选择,只能使用它。)
猜你喜欢
  • 1970-01-01
  • 2011-08-04
  • 2011-01-02
  • 2017-01-15
  • 1970-01-01
  • 2011-04-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多