我使用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));
}
}
一切都在本地工作,但当我在服务器上学习(崩溃)时,我遇到了多个用户的一些问题。
我想我犯了一个错误。我确定我的静态数据存在内存泄漏。
我该如何避免这个问题?我应该使用单身人士吗?
答案 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));
}
}