C# 跨.NET MVC控制器请求持久化变量
我的处境很奇怪——有人要求我优化一个依赖于延迟加载的搜索功能。我已经意识到速度的主要问题是由于分页请求之间的等待时间(大约1.5秒),在代码中,我意识到控制器处理的每个页面请求都会导致模型执行完整的DB查询(而不是仅对该页面的结果进行部分查询) 我们使用的是一个定制的ORM,所以我不确定它在分页方面处理了什么(我想这就是它以这种方式实现的原因)。我们将DB结果存储到IEnumerable,然后使用LINQ进行过滤以检索正确的页面结果 我想做的是将这个请求缓存在内存中——因为我们将把完整的结果放入一个IEnumerable中,所以将其保存在某个地方(即使我必须将其传递到我的模型中)会很方便 有人建议在我的控制器或模型中使用一个静态变量,但我认为如果有多个请求,这将很难失败。我认为可能有一种方法可以暂时将其存储在服务器端会话变量中,并在所有页面请求完成后将其删除。手动缓存,如果您愿意的话 我知道这不是最好的方法,但这可能是我在优化方面唯一明智的选择(除非我们转向另一种ORM)。有人有任何建议、想法或批评吗?我如何实现这样的东西 多谢各位 控制器代码:C# 跨.NET MVC控制器请求持久化变量,c#,asp.net-mvc,caching,paging,C#,Asp.net Mvc,Caching,Paging,我的处境很奇怪——有人要求我优化一个依赖于延迟加载的搜索功能。我已经意识到速度的主要问题是由于分页请求之间的等待时间(大约1.5秒),在代码中,我意识到控制器处理的每个页面请求都会导致模型执行完整的DB查询(而不是仅对该页面的结果进行部分查询) 我们使用的是一个定制的ORM,所以我不确定它在分页方面处理了什么(我想这就是它以这种方式实现的原因)。我们将DB结果存储到IEnumerable,然后使用LINQ进行过滤以检索正确的页面结果 我想做的是将这个请求缓存在内存中——因为我们将把完整的结果放入
[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;
}
public contactsWebView模型GetAccountsWebView(用户,int页)
{
//这就是我希望通过坚持这个值来避免每次都这样做的原因。
//如果有必要,我可以将其传递到这个方法中。
IEnumerable accounts=Context.Get()
.Include(x=>x.AssignedGroups)
.包括(x=>x.AssignedUsers)
.包括(x=>x.联系人)
.其中(x=>x.IsActive)
.OrderBy(x=>x.Name)
.ToArray();
如果(!user.HasPermission(“Administrator.Contacts:View”))accounts=accounts.Where(x=>x.IsReadableBy(user));
inttotalpages=Convert.ToInt32(Math.天花(Convert.ToDouble(accounts.Count())/25.0));
accounts=accounts.Skip(第25页)。Take(第25页);
var model=GetWebView(用户,空,帐户,页面==0);
model.TotalPages=TotalPages;
收益模型;
}
如果要缓存的数据是只读的,并且对于所有用户都是相同的,那么使用静态变量是不存在问题的
如果不是这样,那么您应该将IEnumerable缓存为System.Runtime.Caching.MemoryCache
对象中的CacheItem
。您可以缓存多个版本以适应可能需要的各种场景
有关的详细信息。如果要缓存的数据是只读的,并且对所有用户都是相同的,那么使用静态变量是不成问题的
如果不是这样,那么您应该将IEnumerable缓存为System.Runtime.Caching.MemoryCache
对象中的CacheItem
。您可以缓存多个版本以适应可能需要的各种场景
有关的详细信息。最简单的解决方案可能是使用内置的asp.net缓存。您没有说您正在使用的框架的版本,但是类似的东西应该可以工作
if (HttpContext.Cache["Key1"] == null)
HttpContext.Cache.Add("Key1", "Value 1", null, DateTime.Now.AddSeconds(60),
Cache.NoSlidingExpiration, CacheItemPriority.High, null);
您可以随意调整缓存时间。但是请注意,如果结果很大,并且有多个用户,则很容易耗尽内存或造成巨大的分页延迟
您可以将搜索条件设置为键,只要返回的结果总是相同的搜索条件。最简单的解决方案可能是使用内置的asp.net缓存。您没有说您正在使用的框架的版本,但是类似的东西应该可以工作
if (HttpContext.Cache["Key1"] == null)
HttpContext.Cache.Add("Key1", "Value 1", null, DateTime.Now.AddSeconds(60),
Cache.NoSlidingExpiration, CacheItemPriority.High, null);
您可以随意调整缓存时间。但是请注意,如果结果很大,并且有多个用户,则很容易耗尽内存或造成巨大的分页延迟
您可以将搜索条件设置为键,只要返回的结果总是相同的搜索条件。我最终使用此答案缓存db请求,这太棒了!不幸的是,事实证明,大部分问题都在别处,而且更难优化-(我最终使用这个答案来缓存db请求,这太棒了!不幸的是,事实证明,大部分问题都在其他地方,而且更难优化……:-(