静态字段与会话变量

到目前为止,我一直在使用Session将一些变量从一个页面传递到另一个页面。 例如用户角色。 当用户登录到Web应用程序时,用户的角色ID保留在Session中,并且在应用程序的不同部分检查该角色。 我最近开始考虑为什么不使用静态成员。 我可以在静态字段中存储相同的信息,并在我的应用程序的任何地方轻松访问它(包括静态字段所在的命名空间的任何位置。)我知道使用Session变量有时会派上用场,这样:

  1. 任何类型的数据都可以存储在Session中。 然而,它必须被转换。但静态字段仅接受具有正确数据类型的数据。
  2. 会话变量将在一段时间后过期,这是我们在许多情况下需要的行为。

除了上述之外,还有其他原因我不应该使用静态字段来存储数据并让它随处可用吗?

不,使用静态变量不是要走的路:

  • 如果您的AppDomain被回收,所有静态变量将被“重置”
  • 静态变量不会水平扩展 – 如果您对应用程序进行负载平衡,则命中一个服务器然后另一个服务器的用户将看不到第一个服务器中的静态变量中的数据存储
  • 最重要的是,静态变量将由对该服务器的所有访问共享…它根本不会基于每个用户…而根据您的描述,您不希望用户X看到用户Y的信息。

从根本上说,您有两种选择来传播应用程序周围的信息:

  • 保持客户端,因此每个请求都提供前面步骤的信息。 (这可能会因大量信息而变得笨拙,但对于简单的情况可能很有用。)
  • 保持服务器端,理想情况下以客户端提供会话标识符的某种持久方式(例如数据库)。

如果您可以使用负载平衡来保持所有用户访问同一服务器,并且如果您不介意在AppDomain被回收1或服务器关闭时丢失会话,您可以将其保留在内存中,由会话ID键入… 不过要小心。


1 ASP.NET中可能存在这样的机制,将会话信息从一个AppDomain传播到另一个AppDomain – 我不确定

它们是两个非常不同的东西。

  • 会话可以在进程外使用(对于负载平衡很重要)
  • 由于其处理过程能力,会话可以更加持久。
  • ASP.Net自动管理会话并发。
  • 需要手动同步对静态变量的访问。
  • 静态是整个应用程序域的全局。 如果为一个用户设置静态字段/属性的值,则所有用户将获得相同的值。 不是您的方案中所需的行为。

任何类型的数据都可以存储在Session中。 然而,它必须被转换。但静态字段仅接受具有正确数据类型的数据。

使用辅助类抽象Session值通常很有帮助。 这可以提高可测试性,还允许您强烈键入属性并在类的内部执行强制转换。

例:

public List UserRoles { get { // optionally check that the value is indeed in session, otherwise this // will throw return (List)Session["UserRoles"]; } } 

也可以看看:

  • C#静态变量 – 范围和持久性
  • aspx是否为c#静态变量提供特殊处理

你忘了一件事(我想)

对于应用程序的所有用户,静态数据将是相同的,而会话是“每个用户”。

所以对于你的“用户角色”场景,我希望有趣的结果;)

静态字段将在所有用户之间共享。
在Web环境中,您将有多个线程一起运行。

更新任何静态成员都需要适当的并发控制。 如果出错,这会显着降低您的网站性能。

会话可以移出流程并在Web场中共享。

即使您的应用服务器崩溃,也会存在进程中的会话。