使用大型静态变量是个坏主意吗?

时间:2014-01-29 13:15:39

标签: c# memory-leaks static

我使用ASP.NET MVC 4,我希望加载大量数据并使其在我的所有类中都可访问。 这是我的代码的极简主义样本:

public class MyController : Controller
{
    public static List<MyObject> myList = null;

    public ActionResult Index()
    {
        MyViewModel model = new MyViewModel();
        myList = GetAllData(User.IDentity.Name); // Fill my list with 2k rows
        model.List = myList;

        return View(model);
    }


    public JsonResult GetData(int i)
    {
        return Json(myList.Where(x => x.Data == i));
    }

}

一切都在本地工作,但当我在服务器上学习(崩溃)时,我遇到了多个用户的一些问题。

我想我犯了一个错误。我确定我的静态数据存在内存泄漏。

我该如何避免这个问题?我应该使用单身人士吗?

4 个答案:

答案 0 :(得分:1)

控制器是无状态的,因此每次调用操作都会创建一个控制器的新实例,这会破坏您尝试实现的目的。这说明了通过在构造函数中实现静态实现静态的更好实现:

public MyController()
{
    myList = GetAllData(); 
}

但是,我建议反对这一点,因为我认为这个问题更多是你设计中的一个缺陷,或者是对控制器中状态如何处理的误解 - 他们是无国籍的。

编辑:添加示例以解决注释: 共同的惯例是做以下事项: 1.去掉静电,真的没有收获。

然后:

public ActionResult Index()
    {
        MyViewModel model = new MyViewModel();

        model.List = GetAllData(User.IDentity.Name);;

        return View(model);
    }


    public JsonResult GetData(int i)
    {
        var model = GetAllData(User.IDentity.Name).Where(x => x.Data == i).ToList();
        return Json(model);
    }

您不需要静态,客户端调用Index和GetData永远不会在控制器的同一个实例中执行,静态在这个实例中是无用的。

答案 1 :(得分:0)

使用静态变量有许多缺点,在您的方案中没有理由使用它们。请使用实例变量并像这样初始化它(对于所有控制器操作):

private List<MyObject> myList;

protected override void Initialize(RequestContext requestContext)
{
    myList = GetAllData();
}

public ActionResult Index()
{
    MyViewModel model = new MyViewModel();
    model.List = myList;
    return View(model);
}

public JsonResult GetData(int i)
{
    return Json(myList.Where(x => x.Data == i));
}

答案 2 :(得分:0)

我必须说是,因为事实并非如此。每次调用控制器时,都会创建一个新的实例,并且需要获取每个操作的数据。您可以在控制器中拥有一个属性并在构造函数中填充它,以便在所有操作中重复使用它,但每次调用操作时,它仍然会访问数据库。

public class MyController : Controller
{ 
    private readonly IDataGetter _dataGetter;

    public MyController(IDataGetter dataGetter)
    {
        _dataGetter = dataGetter;
    }

    public ActionResult Index()
    {
        MyViewModel model = new MyViewModel();
        myList = _dataGetter.GetAllData(User.IDentity.Name); // Fill your list with 2k rows
        model.List = myList;

        return View(model);
    }
}

我认为您所追求的是,​​每当您需要来自 GetAllData()的数据时,您不想访问数据库。

我会做什么(假设数据不经常更改,并且您希望在不同的控制器中重用此方法)正在创建 BaseController 并让您的控制器从此继承而不是控制器的。将 OutputCache 添加到该控制器操作,这样您就不必每次都访问数据库。

public class BaseController : Controller
{
    [OutputCache(Duration = 3600)] //cache 3600 sec
    public List<SomeDataModel> GetAllData()
    {
        return _dataGetter.GetAllData(User.Identity.Name);
    }
}

然后,在您要访问数据的所有控制器操作中,您可以调用此基本方法。这将使其保持缓存状态,您无需每次都从数据库中获取它。

var allData = base.GetAllData();

注意:在尝试使用它之前,您应该阅读有关依赖注入和控制反转的内容。

答案 3 :(得分:0)

为什么不使用静态构造函数?它只会填充一次,并且在需要时就可以使用了。

public class MyController : Controller
{
    public static List<MyObject> myList = null;
    static MyController()
    {
        myList = GetAllData(User.IDentity.Name); // Fill my list with 2k rows
    }

    public ActionResult Index()
    {
        MyViewModel model = new MyViewModel();
        model.List = myList;

        return View(model);
    }

    public JsonResult GetData(int i)
    {
        return Json(myList.Where(x => x.Data == i));
    }
}