我正在检索一大堆新闻。
出于显而易见的原因,我想利用此列表的缓存(运行超出必要的查询都行不通)。
我将此列表绑定到一个转发器,我已扩展该中继器以启用分页(在页面之间轻拂会导致页面加载,因此再次检索列表)。
复杂之处在于,这些新闻项也可以从查询字符串"year"中按日期查询,该查询字符串仅在按日期查询新闻项时出现。
以下是我目前拥有的伪代码(在此处粘贴真实代码将花费太多时间来修剪掉所有只会增加混乱的位):
if(complete news items list are not cached OR querystring["year"] != null)
{
Int year = queryString["year"] (could be null)
Cache.Add(GetNewsItems(year));
}
else
{
return cached newsItems;
}
问题是,当新闻项页加载时(由于分页控件的回发),查询字符串的 [year] 参数仍将填充,因此将重新执行 GetNewsItems。此外 - 即使主 URL(即没有查询字符串)然后导航到 - 实际上仍然有新闻项目的缓存版本,因此它不会费心尝试检索它们 - 但它们可能在特定年份存在,因此与"所有年份"类型的搜索无关。
我是否添加新的缓存条目来标记最近执行的搜索?缓存超时需要在此处进行哪些考虑?如果需要(最好不是),我可以添加新的查询字符串 - 这会解决问题吗?
您能否获得第一个查询的完整列表,并缓存此列表(假设它不是太大)?然后,对于任何后续查询,从缓存中获取数据并对其进行查询以筛选出所需的年份。
也许您可以将数据存储在缓存中,形式为
IDictionary<int, IEnumerable<NewsItem>>
(假设一年有多个 NewsItem),其中键是年份,因此您只需检索单个字典值对即可获取一年的数据。
或者,按年份缓存数据,就像在示例中所做的那样,并实现一种机制来从缓存中获取每年的数据(如果存在)。获取所有内容时,您可以只从数据存储中获取所有内容并单独缓存,也可以实现某种机制来确定缓存中缺少哪些年份并仅获取这些年份。就个人而言,我认为我会缓存所有并从缓存中过滤数据,以免缓存数据过多堵塞内存。
从缓存中获取的有用的 TryGetValue 模式如下所示:
private bool TryGetValue<U>(string key, out U value)
{
object cachedValue = HttpContext.Current.Cache.Get(key);
if (cachedValue == null)
{
value = default(U);
return false;
}
else
{
try
{
value = (U)cachedValue;
return true;
}
catch
{
value = default(U);
return false;
}
}
}
不确定这是否对您的情况有帮助,但您可以将转发器添加到用户控件,并为其启用 OutputCache,使其失效 POST/GET 参数:
<%@ OutputCache Duration="100" VaryByParam="year" %>