我处于一种奇怪的境地 - 我被要求优化依赖于延迟加载的搜索功能。我已经意识到速度的主要问题是由于寻呼请求之间的等待时间(大约1.5秒)而在代码中,我意识到控制器处理的每个页面请求都会导致模型执行完整的数据库查询(而不是仅对该页面的结果进行部分查询。)
我们正在使用自定义ORM,因此我不确定它在分页方面的处理方式(我认为这就是为什么以这种方式实现)。我们将DB结果存储到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;
}
答案 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);
您可以根据需要调整缓存时间。但请注意,如果结果很大,并且您有多个用户,则很容易耗尽内存或导致大量的分页延迟。
您可以将搜索条件作为关键,只要始终使用相同的搜索条件返回相同的结果。
答案 1 :(得分:1)
如果您要缓存的数据是只读的并且对所有用户都相同,则使用static
变量不是问题。
如果不是这种情况,那么您应该将IEnumerable作为CacheItem
缓存在System.Runtime.Caching.MemoryCache
对象中。您可以缓存多个版本以适应可能需要的各种方案。
有关MemoryCache on MSDN的更多信息。