2010-08-24 255 views
3

我有一个静态变量的问题。我的控制器的组织部分如下:静态变量问题

namespace MyApp.Controllers 
{ 
    public class DevicesController : Controller 
    {    
     static int some_var = 0;   

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult SetValue(int temp){ 
      some_var = temp; 
      return RedirectToAction("DisplayValue"); 
     } 

     [Authorize] 
     public ActionResult DisplayValue(){    
      .... 
      return View(some_object); 
     } 
    } 
} 

当多个用户同时使用此视图时,会出现问题。所有用户使用相同的静态变量并更改其值。如何解决此问题?

回答

7

可以使用,

HttpContext.Current.Session["some_var"] 

代替some_var,这将帮助。这将保留该记录,一个会话的用户,你可以用HttpContext.Current

namespace MyApp.Controllers 
{ 
    public class DevicesController : Controller 
    { 

     [AcceptVerbs(HttpVerbs.Post)] 
     public ActionResult SetValue(int temp){ 
      HttpContext.Current.Session["some_var"] = temp; 
      return RedirectToAction("DisplayValue"); 
     } 

     [Authorize] 
     public ActionResult DisplayValue(){ 

      .... 
      return View((int)HttpContext.Current.Session["some_var"]); 
     } 
    } 
} 
+0

在哪里我可以找到任何示例工作与会话状态的保存值 – Ognjen 2010-08-24 13:55:35

+0

我使用您的代码时出现此错误: 'System.Web.HttpContextBase'没有包含'当前'的定义和没有扩展方法'当前'接受'System.Web.HttpContextBase'类型的第一个参数可以找到(你是否缺少使用指令或程序集引用?) – Ognjen 2010-08-24 14:07:24

+1

我建议不要使用HttpContext.Current.Session。只要使用Session,它就是ViewContext的一部分。使用HttpContext.Current通常不是一个好主意在MVC的土地:) – CubanX 2010-08-24 14:12:25

6

使其成为私有实例变量,而不是静态的。

如果你需要每个用户维护这个计数(但只能用于指定会话),那么你就可以做到以下几点:

if (Session["Count"] == null) 
    Session["Count"] = 0; 
Session["Count"] = (int)Session["Count"] + MyNewValue; 

如果你想计数跨会话持续下去,那么你能坚持它到一个数据库。

+0

如果我把它设为私人,那么我会损失'some_var'的值。 – Ognjen 2010-08-24 13:03:57

+0

听起来你想维护每个用户的值*,所以它应该被保存到会话中,或者保存到具有相关用户ID的数据库中。 – RedFilter 2010-08-24 13:54:03

+0

在那里我可以找到这个例子 – Ognjen 2010-08-24 14:02:35

1

静态变量(和属性)将在该类型的所有实例中共享 - 在本例中为您的控制器。当应用程序池重新启动时,该值将丢失。

如果您需要持续保存各个请求的值,对于特定用户,则可能需要将其移至会话或类似位置。

如果您只需要在当前请求期间保留该值,那么私有变量就足够了。

+0

我需要在特定用户的请求中持续存在的值,在会话中使用静态变量的任何示例 – Ognjen 2010-08-24 13:07:08

+0

Ognjen:整个会话对象(HttpContext.Current.Session)是静态的。请参阅Akash的回应或查看如何在ASP.NET中使用会话。 :) – Teekin 2010-08-24 13:15:43

1

静态访问它有类变量和对象变量之间的重要区别。静态变量是类变量,这意味着从一个类实例化的所有对象共享相同的变量,因此对象中该静态变量的变化也会更改同一类的其他对象。 但是为每个实例化对象创建一个非静态变量(对象变量),所以更改不会影响其他实例。

但问题不在于选择这两者,因为您的需求不同。您需要为每个用户保留一个变量。正如其他人所说,你必须使用会话变量。

但我认为你应该阅读关于对象变量和类变量。

+0

+1:理解任何编程任务的重要区别。 – RedFilter 2010-08-24 15:26:04

8

您的整个 ASP.NET MVC应用程序在AppDomain内运行,这是应用程序加上所有请求正在为所有用户服务,一切!

当您创建一个静态变量时,会声明一个实例并将其提供给整个AppDomain,每个用户的每个请求都会看到相同的值。

一个实例变量(简单地删除'静态'字)是特定于它所在的特定对象的一个​​实例。在这种情况下,该对象是您的Controller实例,因此您的变量作为实例变量将是单独的/只针对该控制器对象。 ASP.NET运行时将为其所服务的每个请求创建一个Controller实例,然后在处理请求后丢弃该控制器对象。因此,如果您删除静态字词,该变量将只在该请求的持续时间内保留,然后消失。

正如其他海报所说,您需要的是会话状态。会话状态持续会话的持续时间,就像在浏览您的网站的用户中一样,并且特定于每个用户。因此,如果您将该变量存储在会话状态中,则每个用户都会有所不同。

问题是当用户离开你的网站时会话状态消失,所以如果你需要它留在更长的时间,那么你应该使用类似数据库的东西。


从您的意见和原来的职位,它的声音(我会尝试尽可能礼貌把这个作为可能的),你还没有完全掌握了一些面向对象的编程风格和概念。虽然会话状态本身不是OOP概念,但静态变量和实例变量之间的区别是。我会建议刷新这些,作为对这些概念的理解(面向对象编程)意味着,恕我直言,你甚至不会问这个问题。我希望这个答案有助于你的理解。

0

静力学既不好也不坏。他们只是有不同的使用结构。 请考虑您正在处理国际电话号码。 为了做到这一点,您至少需要一个country_code,国家和唯一的ID。您可能还需要IDD国家/地区转义前缀。 因此,您创建一个对象来保存所有这些,然后将它们从数据库或其他方法收集到列表中。 您希望下拉列表中列出用户选择的国家,然后您希望country_code与您收集的任何内容一致。 如果您将国家/地区对象列表创建为静态,那么当您进行往返服务器往返时,您无需每次都从其后备存储库重新加载列表,只需使用它填充下拉列表。由于这些数据永远不会改变,因此可以将其设置为静态。网站上的每个人都将使用相同的国家列表,因此拥有一份副本并不重要。但是,您必须使ID用于非静态列表索引,以便在列表中恢复选择时,每个人都有自己的选择,而不是全局静态的,它显示最后一个人选择的内容。 将您的模型设置为非静态的county_code_id以使用列表中选定的ID,然后当您准备好更新数据时,请使用模型country_code_id查找country对象列表中的country_code,以返回country_code以供更新。

就像我说过的,静力学既不好也不坏,它们只是有不同的用法。