我有一个MVC 5网站,它使用Entity Framework进行数据库交互.
我想在控制器中使用IEnumerable作为私有变量,以便同一控制器中的其他自定义ActionResults可以使用相同的信息,而无需每次都重新查询.我不是指其他CRUD ActionResults,而是指其他自定义方法,这些方法使用在Index页面上看到的数据执行操作,该页面通常是完整数据库表的子集.查询一次然后重新使用相同的数据会很有帮助.
在这个例子中,我有private IEnumerable
一个类级变量和IEnumerable
一个Index()级变量.我Debug.WriteLine
用来确定每个变量是否为空.
正如我所料,在Index()ActionResult的范围内,变量data和_data都不为null.内ClickedFromIndexPageLink()的范围内,_data -类级别变量为空.
我的理论是,虽然我首先按顺序加载了索引,但控制器并不知道.就控制器而言,当我在另一个ActionResult中请求_data内容时,它还没有被填充.然而,在现实的时候,我已经按下指数第一,所以应该会看到_data充满指数查询.
要查看我的解决方法,请向下滚动以查看"方法B(确实有效,但重复)".
有没有简单的方法让IEnumerable以这种方式用作私有类变量,或者我的解决方法是唯一可行的方法?
方法A(不起作用):
Debug.WriteLine()结果:
Begin Index() test ***** Is data Null? Not Null Is _data Null? Not Null End Index test ***** Begin ClickedFromIndexPageLink() test***** Is _data Null? Null End ClickedFromIndexPageLink test*****
代码:
using IenumerableAsClassVariable.Models; using System.Collections.Generic; using System.Data.Entity; using System.Diagnostics; using System.Linq; using System.Net; using System.Web.Mvc; namespace IenumerableAsClassVariable.Controllers { // This is the helper class & function used to determine if the IEnumerable is null or empty public static class CustomHelpers { public static string IsNullOrEmpty(this IEnumerable enumerable) { if (enumerable == null) return "Null"; else return "Not Null"; } } public class CourseListsController : Controller { private CreditSlipLogContext db = new CreditSlipLogContext(); private IEnumerable _data; // If IEnumerable is null or empty return true; else false. // GET: CourseLists public ActionResult Index() { IEnumerable data = db.CourseLists.AsEnumerable(); Debug.WriteLine("-----"); Debug.WriteLine("Begin Index test *****"); Debug.WriteLine("Is data Null? " + CustomHelpers.IsNullOrEmpty(data)); _data = data; Debug.WriteLine("Is _data Null? " + CustomHelpers.IsNullOrEmpty(_data)); Debug.WriteLine("End Index test *****"); return View(db.CourseLists.ToList()); } public ActionResult ClickedFromIndexPageLink() { Debug.WriteLine("Begin ClickedFromIndexPageLink test*****"); Debug.WriteLine("Is _data Null? " + CustomHelpers.IsNullOrEmpty(_data)); Debug.WriteLine("End ClickedFromIndexPageLink test*****"); ViewBag.IsDataNull = CustomHelpers.IsNullOrEmpty(_data); return View(); } #region OtherCrudActionResultsAreHidden #endregion } }
方法B(确实有效,但重复):
正如我所料,我的结果不是空的:
Begin ClickedFromIndexPageLink test***** Is data Null? Not Null Is _data Null? Not Null End ClickedFromIndexPageLink test*****
这是因为我在ActionResult中重新查询,就像我在Index()ACtionResult中一样:
public ActionResult ClickedFromIndexPageLink() { IEnumerabledata = db.CourseLists.AsEnumerable(); Debug.WriteLine("Begin ClickedFromIndexPageLink test*****"); Debug.WriteLine("Is data Null? " + CustomHelpers.IsNullOrEmpty(data)); _data = data; Debug.WriteLine("Is _data Null? " + CustomHelpers.IsNullOrEmpty(_data)); Debug.WriteLine("End ClickedFromIndexPageLink test*****"); ViewBag.IsDataNull = CustomHelpers.IsNullOrEmpty(_data); return View(); }
Shyju.. 5
每次调用action方法都是一个单独的Http请求.请记住,Http是无状态的,并且一个请求不知道先前的请求是做什么的.因此,您将无法获得在上一个操作方法调用中设置的私有变量值.
您可以考虑缓存多个请求可用的数据,直到缓存过期.您可以使用MemoryCache
dot net中提供的类.
快速样品
const string CacheKey = "courses"; public ActionResult Index() { var courseList = GetCourses(); // do something with courseList return View(courseList ); } public ActionResult List() { var course = GetCourses(); // do something with courseList return View(course); } private ListGetCourses() { var db = new YourDbContext(); var cache = MemoryCache.Default; if (!cache.Contains(CacheKey)) // checks to see it exists in cache { var policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTime.Now.AddDays(1); var courses = db.CourseLists.ToList(); cache.Set(CacheKey , courses, policy); } return (List ) cache.Get(CacheKey); }
当然,您可以将其从控制器代码移到新的类/层,以保持关注点分离.
如果您希望在存储到缓存之前将实体对象转换为简单的POCO/ViewModel集合,
var courseVms = db.CourseLists.Select(s=>new CourseViewModel { Id =s.Id, Name=s.Name }).ToList(); cache.Set(cacheKey, courseVms , policy);
而你的GetCourses方法将返回一个 List
请记住,缓存将保留数据,直到缓存过期.因此,保留通常不会经常更改的数据是一个好主意(例如:查找数据等).如果要缓存事务数据,则每次对数据进行更改时都需要更新缓存(例如:添加新课程,删除一门课程等).
MemoryCache
class驻留在驻留的System.Runtime.Caching
名称空间中System.Runtime.Caching.dll
.因此,您需要添加对此程序集的引用.
如果要在ASP.NET5/MVC6应用程序中执行相同类型的缓存,可以IMemoryCache
按照本答案中的说明使用实现.
每次调用action方法都是一个单独的Http请求.请记住,Http是无状态的,并且一个请求不知道先前的请求是做什么的.因此,您将无法获得在上一个操作方法调用中设置的私有变量值.
您可以考虑缓存多个请求可用的数据,直到缓存过期.您可以使用MemoryCache
dot net中提供的类.
快速样品
const string CacheKey = "courses"; public ActionResult Index() { var courseList = GetCourses(); // do something with courseList return View(courseList ); } public ActionResult List() { var course = GetCourses(); // do something with courseList return View(course); } private ListGetCourses() { var db = new YourDbContext(); var cache = MemoryCache.Default; if (!cache.Contains(CacheKey)) // checks to see it exists in cache { var policy = new CacheItemPolicy(); policy.AbsoluteExpiration = DateTime.Now.AddDays(1); var courses = db.CourseLists.ToList(); cache.Set(CacheKey , courses, policy); } return (List ) cache.Get(CacheKey); }
当然,您可以将其从控制器代码移到新的类/层,以保持关注点分离.
如果您希望在存储到缓存之前将实体对象转换为简单的POCO/ViewModel集合,
var courseVms = db.CourseLists.Select(s=>new CourseViewModel { Id =s.Id, Name=s.Name }).ToList(); cache.Set(cacheKey, courseVms , policy);
而你的GetCourses方法将返回一个 List
请记住,缓存将保留数据,直到缓存过期.因此,保留通常不会经常更改的数据是一个好主意(例如:查找数据等).如果要缓存事务数据,则每次对数据进行更改时都需要更新缓存(例如:添加新课程,删除一门课程等).
MemoryCache
class驻留在驻留的System.Runtime.Caching
名称空间中System.Runtime.Caching.dll
.因此,您需要添加对此程序集的引用.
如果要在ASP.NET5/MVC6应用程序中执行相同类型的缓存,可以IMemoryCache
按照本答案中的说明使用实现.