2014-02-09 34 views
0

我处于一种奇怪的情况 - 我被要求优化依赖于延迟加载的搜索功能。我意识到速度的主要问题是由于分页请求(大约1.5秒)和代码之间的等待时间,我意识到控制器处理的每个页面请求都会导致模型执行完整的数据库查询(而不是仅针对该页面的结果的部分查询)。在.NET MVC控制器请求中坚持一个变量

我们使用的是自定义的ORM,所以我不确定它在分页方面如何处理(我认为这就是为什么以这种方式实现的原因)。我们将数据库结果存储到IEnumerable中,然后使用LINQ进行筛选以检索正确的页面结果。

我想要做的就是将这个请求缓存在内存中 - 因为我们把完整的结果放到一个IEnumerable中,将它放在某个地方会很方便(即使我必须将它传递到我的模型)。

有人建议在我的控制器或模型中使用静态变量,但我认为这会在多个请求中失败。我在想,可能会有一种方法将其暂时存储在服务器端的Session变量中,并在所有页面请求完成后将其删除。手动缓存,如果你愿意。

我知道这不是最好的方式来做到这一点,但它可能是我在优化方面唯一的理智选择(除非我们转向不同的ORM)。有没有人有任何建议,想法或批评?我将如何实现这样的事情?

谢谢。

控制器代码:

[HttpGet, JsonErrorCatcher, NoCache] 
    public ActionResult Accounts(int page = 0) 
    { 
     using (var context = PersistenceContext.Create()) 
     { 
      var model = new ContactsModel(context); 
      return new JsonNetResult(model.GetAccountsWebView(CurrentUser, page)); 
     } 
    } 

型号方法:

public ContactsWebViewModel GetAccountsWebView(User user, int page) 
    { 
     // This is what I'd like to avoid doing every time, by persisting this value. 
     // I can pass it into this method if necessary. 
     IEnumerable<Account> accounts = Context.Get<Account>() 
      .Include(x => x.AssignedGroups) 
      .Include(x => x.AssignedUsers) 
      .Include(x => x.Contacts) 
      .Where(x => x.IsActive) 
      .OrderBy(x => x.Name) 
      .ToArray(); 
     if (!user.HasPermission("Administrator.Contacts:View")) accounts = accounts.Where(x => x.IsReadableBy(user)); 
     int totalPages = Convert.ToInt32(Math.Ceiling(Convert.ToDouble(accounts.Count())/25.0)); 
     accounts = accounts.Skip(page * 25).Take(25); 
     var model = GetWebView(user, null, accounts, page == 0); 
     model.TotalPages = totalPages; 
     return model; 
    } 

回答

1

如果你希望缓存中的数据是只读的并且同样为所有用户,然后用static变量是一个非问题。

如果不是这种情况,那么您应该将IEnumerable作为CacheItem缓存在System.Runtime.Caching.MemoryCache对象中。您可以缓存多个版本以适应可能需要的各种场景。

更多关于MemoryCache on MSDN

+0

我最终使用这个答案缓存数据库请求,这太棒了!不幸的是,事实证明,这个问题的大部分都来自其他地方,而且要优化更难:....-( –

2

最简单的解决方案可能是使用内置的asp.net缓存。你不会说你使用的是什么版本的框架,但是这样的东西应该可以工作。

if (HttpContext.Cache["Key1"] == null) 
    HttpContext.Cache.Add("Key1", "Value 1", null, DateTime.Now.AddSeconds(60), 
     Cache.NoSlidingExpiration, CacheItemPriority.High, null); 

不管你喜欢,你都可以调整缓存时间。但请注意,如果结果很大,并且您拥有多个用户,则可能会导致内存不足或导致大量的分页延迟。

您可以使搜索条件成为关键,只要结果相同总是以相同的搜索条件返回。

相关问题