我有一个处理程序(例如list.ashx),它有一个检索大数据集的方法,然后只抓取将在任何给定的“页面”数据上显示的记录。我们允许用户对这些结果进行排序。因此,在任何给定的页面运行中,我将检索几秒钟/几分钟前刚刚获得的数据集,但是重新排序它们,或显示下一页数据等。
我的观点是我的数据集确实没有改变。通常,数据集会粘在页面的视图状态中,但由于我使用的是处理程序,因此我没有那么方便。至少我不这么认为。
那么,在使用处理程序时,存储与当前用户的给定页面关联的视图状态的常用方法是什么?有没有办法获取数据集,以某种方式对其进行编码并将其发送回用户,然后在下一次调用时,将其传回,然后从这些位重新水化数据集?
我认为Session不是一个存储它的好地方,因为我们可能有1000个用户都在查看不同数据的不同数据集,这可能会使服务器陷入困境。至少我是这么认为的。
有没有人有这种情况的经验,你能给我任何建议吗?
答案 0 :(得分:3)
在这种情况下,我会使用具有某种类型的用户和查询信息的缓存作为密钥。原因是你说它是一个大型数据集。对,有些东西你不想一直在管道上下推动。请记住,如果数据在ViewState中并且处理它,您的服务器仍然必须接收数据。我会做这样的事情,它会为特定用户缓存它并且有一个短暂的到期时间:
public DataSet GetSomeData(string user, string query, string sort)
{
// You could make the key just based on the query params but figured
// you would want the user in there as well.
// You could user just the user if you want to limit it to one cached item
// per user too.
string key = string.Format("{0}:{1}", user, query);
DataSet ds = HttpContext.Current.Cache[key] as DataSet;
if (ds == null)
{
// Need to reload or get the data
ds = LoadMyData(query);
// Now store it and make the expiry short so it doesn't bog up your server
// needlessly... worst case you have to retrieve it again because the data
// has expired.
HttpContext.Current.Cache.Insert(key, ds, null,
DateTime.UtcNow.AddMinutes(yourTimeout),
System.Web.Caching.Cache.NoSlidingExpiration);
}
// Perform the sort or leave as default sorting and return
return (string.IsNullOrEmpty(sort) ? ds : sortSortMyDataSet(ds, sort));
}
当你说1000个用户时,这是否意味着并发用户?如果您的到期时间是1分钟,那么有多少并发用户会在一分钟内拨打该电话并需要排序。我认为将数据卸载到与ViewState
类似的东西只是为了带宽和来回处理大量请求的负载而交换一些高速缓存。在我看来,你来回传递的越少越好。
答案 1 :(得分:2)
为什么不实现服务器端缓存?
据我所知,您正在检索大量数据,然后仅将此数据中的必要记录返回给不同的客户端。所以你可以使用HttpContext.Current.Cache
属性。
E.g。可以使用封装数据检索逻辑的属性(使用第一个请求从原始数据存储获取,然后放入缓存并从每个下一个请求获取缓存)。在这种情况下,所有必要的数据操作(分页等)可以比使用每个请求检索大量数据更快地完成。
在客户端具有不同数据源(意味着每个客户端都有自己的数据源)的情况下,也可以实现上述解决方案。我想每个客户端至少都有标识符,因此您可以为不同的客户端使用不同的缓存(客户端标识符作为缓存密钥的一部分)。
答案 2 :(得分:1)
通过将请求正文中的序列化数据集包含在ASHX处理程序中,您可以做的最好的事情就是“发展自己”。然后,您的处理程序将通过检查Request.ContentLength
然后从Request.InputStream
读取,以及是否将该主体序列化回数据集而不是从数据库中读取来检查请求是否确实具有正文。