我的静态变量有问题。我的控制器组织的一部分如下:
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);
}
}
}
当多个用户同时使用此视图时,会出现问题。所有用户都使用相同的静态变量并更改其值。怎么解决这个问题?
答案 0 :(得分:8)
您的整个 ASP.NET MVC应用程序在AppDomain
内运行,即应用程序以及为所有用户提供的所有请求,一切!!
当您创建静态变量时,会声明单个实例并使其可供整个AppDomain使用,每个用户的每个请求都会看到相同的值。
实例变量(简单地删除'静态'字)特定于它所在的特定对象的实例。在这种情况下,对象是Controller的一个实例,因此作为实例变量的变量将是个体/特定于该控制器对象。 ASP.NET运行时将为其服务的每个请求创建一个Controller实例,然后在处理完请求后丢弃该控制器对象。因此,如果删除静态单词,变量将仅在该请求的持续时间内保持不变,然后消失。
正如其他海报所说,你需要的是会话状态。会话状态持续会话的持续时间,如浏览您网站的人,并且特定于每个用户。因此,如果您将该变量存储在会话状态中,则每个用户都会有所不同。
问题是当用户离开你的网站时会话状态消失,所以如果你需要更长时间停留,那么你应该使用类似数据库的东西。
从您的评论和原始帖子中,听起来(我会尽可能礼貌地表达这一点),您还没有完全掌握一些面向对象的编程习语和概念。虽然会话状态本身不是OOP概念,但静态和实例变量之间的差异是。我建议了解这些,因为理解这些概念(OO编程的基础)意味着,恕我直言,你甚至不会问这个问题。我希望这个答案对你的理解有所帮助。
答案 1 :(得分: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"]);
}
}
}
答案 2 :(得分:6)
将其设为私有实例变量,而不是静态变量。
如果您需要为每个用户维护此计数(但仅限于给定的会话),则可以执行以下操作:
if (Session["Count"] == null)
Session["Count"] = 0;
Session["Count"] = (int)Session["Count"] + MyNewValue;
如果您希望计数在会话中持续存在,那么您可以将其持久保存到数据库中。
答案 3 :(得分:1)
静态变量(和属性)将在该类型的所有实例之间共享 - 在本例中为您的控制器。重新启动应用程序池时,该值将丢失。
如果您需要将值保留在请求之间,对于特定用户,则可能需要将其移至会话或类似用途。
如果您只需要在当前请求的持续时间内保留该值,那么私有变量就足够了。
答案 4 :(得分:1)
类变量和对象变量之间存在重要差异。静态变量是类变量,这意味着从类实例化的所有对象共享相同的变量,因此对象中该静态变量的更改也会更改同一类的其他对象。 但是为每个实例化对象创建了一个非静态变量(对象变量),因此更改不会影响其他对象。
但问题不在于选择这两者,因为你的需求是不同的。您需要为每个用户保留一个变量。正如其他人所说,你必须使用会话变量。
但我认为你应该读一下对象变量和类变量。
答案 5 :(得分:0)
静力既不好也不坏。它们只是具有不同的使用结构。 请考虑您正在处理国际电话号码。 为了做到这一点,您至少需要country_code,country和唯一ID。您可能还需要IDD国家/地区转义前缀。 因此,您创建一个对象来保存所有这些,然后将它们从数据库或其他方法收集到列表中。 您想要一个下拉列表来列出用户选择的国家/地区,然后您希望country_code与您正在收集的内容一起使用。 如果您将国家/地区对象列表创建为静态,那么当您进出往返服务器的往返时,您不必每次都从它的后备存储中重新加载列表,您只需使用它即可填充下拉列表。由于这些数据永远不会改变,因此可以将其设置为静态。网站上的每个人都将使用相同的国家/地区列表,因此拥有一份副本并不重要。但是,您必须将用于索引列表的Id设置为非静态,以便在列表中恢复选择时,每个人都有自己的选择,而不是显示最后一个人选择内容的全局静态选择。 将模型设置为非静态county_code_id以使用列表中选择的ID,然后在准备好更新数据时,使用模型country_code_id查找country对象列表中的country_code以返回country_code以进行更新。
就像我说的那样,静力学既不好也不坏,它们只是有不同的用法。