6

我想以类似于CodeProject 上讨论的方式包装 Session 变量。

public static class WebSession
{
  private const string CurrentUserKey = "CurrentUser";

  private static HttpSessionState Session
  {
    get { return HttpContext.Current.Session; }
  }

  public static bool Exists
  {
    get { return Session != null; }
  }

  public static User CurrentUser
  {
    get { return Session[CurrentUserKey] as User; }
    set { Session[CurrentUserKey] = value; }
  }
}

这是我的问题:如果我必须在同一页面中访问CurrentUser多次,是否可以通过将其分配给局部变量而不是访问包装属性来提高性能?或者是否HttpSessionState确保每个请求只对对象进行一次反序列化,以便在同一个 http 请求中的后续调用不再花费更多?

谢谢,亚伦

4

4 回答 4

6

每个请求都有一个 Session 状态的内存副本。因此,通过本地复制会话变量可以节省的唯一成本是从 Object 转换为您的类型的成本。然后在请求结束时将内存中的副本添加到 Session 中。

Session 是否在页面上进行序列化和反序列化取决于您选择的 Session Provider。对于进程内会话状态,不会发生序列化。对于会话服务器,对象必须首先被序列化。

于 2010-01-27T21:54:24.930 回答
4

有一个内存副本。您从缓存值中获得的性能提升可以忽略不计;它只会保存一个字典查找,这将太快而无法注意到,除非您在每次页面加载时执行无数次。

另外需要注意的是,对于给定的键,每次检索都返回对同一实例的引用,并且 Session 也保留一个引用。这意味着,如果您从 Session 检索对象并对其进行修改,则无需再次调用 setter 来重新序列化它。

我刚刚问了一个关于同一件事的问题: .Net 属性设置器是否曾被隐式调用?

于 2010-01-27T23:08:26.320 回答
3

我最近做了一些拆开会话的工作,据我所见,整个状态对象仅在每个请求中反序列化一次。当然,检查很容易——只需将其取出两次并检查ReferenceEquals

当然,将值放在两次使用之间的字段中会节省一些“查找”时间,但您应该只支付一次反序列化成本。

如果您真的想确定,您还可以通过实现ISerializable和记录序列化/反序列化调用来仔细检查这一点。

于 2010-01-27T21:55:03.270 回答
0

一些值得阅读的好文章

http://msdn.microsoft.com/en-us/library/aa479041.aspx

http://msdn.microsoft.com/en-us/magazine/cc163730.aspx#S5

于 2010-01-27T21:44:58.783 回答