Session vs singleton模式

时间:2010-05-12 19:07:32

标签: c# asp.net asp.net-mvc design-patterns

我有一个Web应用程序,我想从数据库中提取用户设置并存储它们以进行全局访问。将数据存储在Singleton或Session对象中会更有意义吗?这两者有什么区别?

将数据存储为对象引用或将其分解为值类型对象(整数和字符串)是否更好?

5 个答案:

答案 0 :(得分:11)

会话。这就是它的用途。会话存储在全局缓存(基本上是单例)中,由会话ID键入。这样,您只获得感兴趣的会话的数据。使用单例基本上会复制全局缓存,您必须重新发明机制以独立地检索每个会话的数据。

继续存储对象。让会话担心将其序列化为可以恢复的东西。但是,请注意您在会话中添加的内容。您不希望在那里存储太多数据,或者您将耗尽大量内存(假设内存缓存)。

答案 1 :(得分:4)

如果这些设置将用于站点的所有用户,请将它们放在单个或应用程序缓存中。如果它们特定于每个用户,请将它们放入会话中。

添加到应用程序或会话缓存时使用对象引用 - 我相信值类型将被装箱,因此它们看起来像缓存的对象。如果你使用单身,它可以采用任何一种方式。

答案 2 :(得分:2)

会话对象,当然。

单身人士存在于流程层面。这意味着如果您有20个用户在任何给定时刻访问您的网站,他们将使用相同的单一对象。如果你不经常进行网络开发,很难习惯这个概念。

会话存在于用户级别。这意味着您可以按用户存储数据,而不是按进程存储数据。

答案 3 :(得分:0)

有时我喜欢以下方法。它处理魔术字符串和未设置的会话变量的问题。它还在会话级别而不是应用程序级别运行单例。

public static SessionHandler GetInstance()
    {
        if (HttpContext.Current.Session["SessionHandler"] == null)
        {
            HttpContext.Current.Session["SessionHandler"] = new SessionHandler();
        }
        return (SessionHandler)HttpContext.Current.Session["SessionHandler"];
    }

然后将其用作普通单身人士。输入你需要的变量。

答案 4 :(得分:0)

这是从旧文档中获取的,但它仍然非常有效并且有效...我会将链接内容放在这里,特别是因为它是一个可能会消失的旧链接。 Taken from here.

<强>背景

ASP.Net中的Session对象可用于存储特定于站点的单个用户的信息。会话由密钥名称索引,当以这种方式直接使用会话时,会导致大量的单个会话名称。另一种方法是改为创建单个对象以对相关项进行分组,并使用给定的键名存储该对象。 “singleton”是一种常见的设计模式,它指定如何确保任何时候只存在一个类的单个实例。

单身会话对象的优点

  • 为组织目的分组会话项目
  • 特别适用于瞬态过程的一系列页面,例如网站注册。一旦完成该过程,就可以从会话中清除对象,从而可以回收内存(更好地使用服务器) 资源)
  • 对会话信息更改的影响分析更加容易
  • 识别滥用信息的网站区域(比仅使用变量名称更清楚以确定是否适合使用)
  • 一旦访问对象,属性名称和类型的智能感知

单身会话对象的缺点

更难以查看会话中单个项目的数量 ASP.Net Trace结果不显示对象内的值 使用进程外会话状态存储时的性能下降(影响序列化)

<强>实施

第一个实现步骤是创建一个类文件,该文件表示应该在单个对象中一起存储的项的逻辑分组。以下是演示该技术的示例类:

public class singleton
{
  //Name that will be used as key for Session object
  private const string SESSION_SINGLETON = "SINGLETON";

  //Variables to store the data (used to be individual
  // session key/value pairs)
  string lastName = "";
  string firstName = "";

  public string LastName
  {
    get
    {
      return lastName;
    }
    set
    {
      lastName = value;
    }
  }

  public string FirstName
  {
    get
    {
      return firstName;
    }
    set
    {
      firstName = value;
    }
  }

  //Private constructor so cannot create an instance
  // without using the correct method.  This is 
  // this is critical to properly implementing
  // as a singleton object, objects of this
  // class cannot be created from outside this
  // class
  private singleton()
  {
  }

  // Create as a static method so this can be called using
  // just the class name (no object instance is required).
  // It simplifies other code because it will always return
  // the single instance of this class, either newly created
  // or from the session
  public static singleton GetCurrentSingleton()
  {
    singleton oSingleton;

    if (null == System.Web.HttpContext.Current.Session[SESSION_SINGLETON])
    {
      //No current session object exists, use private constructor to 
      // create an instance, place it into the session
      oSingleton = new singleton();
      System.Web.HttpContext.Current.Session[SESSION_SINGLETON] = oSingleton;
    }
    else
    {
      //Retrieve the already instance that was already created
      oSingleton = (singleton)System.Web.HttpContext.Current.Session[SESSION_SINGLETON];
    }

    //Return the single instance of this class that was stored in the session
    return oSingleton;
  }
}

想要使用此对象的页面只执行以下操作:

singleton oSingleton = singleton.GetCurrentSingleton();
oSingleton.FirstName = "Robert";
oSingleton.LastName = "Boedigheimer";

通常,此技术将在给定类中存储更多变量,或者将用于执行过程的一系列网页。将其用于网站上的进程的另一个优点是,只需删除对单例对象的引用即可清除会话变量所需的所有内存。该类可以实现客户端可以用来清除引用的方法,当类提供清理方法时,可以将其命名为Dispose()以遵循典型的.Net模式:

public static void Dispose()
{
    //Cleanup this object so that GC can reclaim space
    System.Web.HttpContext.Current.Session.Remove(SESSION_SINGLETON);
}

<强>结论

使用存储在Session对象中的单例对象而不是使用单个会话密钥来存储信息有许多优点。它对于整个会话中存在的对象(分组逻辑项,影响分析,智能感知等)非常有用,特别是对于在网站上一段时间内真正需要的对象,直到用户完成特定对象过程(更容易识别错误使用变量并在过程完成但节点将继续时节省资源)。