ASP.NET:保存 WebConfigurationManager 时 HttpRuntime.Cache 被刷新——这是一个错误吗?
最近,我一直在尝试使用 HttpRuntime.Cache 缓存对象,我通常的印象是,如果我向缓存“添加”一些内容,如下所示:
HttpRuntime.Cache.Insert("Test", "This is a test!", null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(FileChanged));
“NotRemovable”和“NoExpiration”标志将在应用程序运行期间将对象保留在内存中。但发现在某些页面请求结束时,HttpRuntime.Cache 将完全为空!
跟踪并在我的回调“FileChanged”中设置断点,我可以看到确实有东西正在“删除”我的对象(以及缓存中的所有其他对象),但我无法弄清楚为什么。所以最终,我开始禁用我认为可能影响该子系统的其他功能。
最终,我注释掉了这一行:
WebConfigurationManager.OpenWebConfiguration("~").Save;
我主要是从 AppSettings 区域中的“web.config”检索数据,但偶尔会写回 AppSettings 并使用上述命令保存更改。我从阅读中知道“web.config”已被缓存,但是将我的更改保存回它不应该刷新所有 HttpRuntime.Cache,对吧?
这是一个错误吗?或者这两个缓存是否以某种方式链接在一起,我应该知道?
编辑:
好吧,如果有人想在自己的机器上尝试这个,我已经使这个超级可重现。 (我正在运行 VS2008 Pro w/ MVC2,目标是 .NET 3.5)只需启动一个新的 MVC2 项目,并将以下内容粘贴到 HomeController
中,覆盖已有的内容:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Configuration;
using System.Configuration;
namespace BackButtonTest.Controllers
{
[HandleError]
public class HomeController : Controller
{
private string MESSAGE = "Message";
public ActionResult Index()
{
ViewData[MESSAGE] = HttpRuntime.Cache.Get(MESSAGE);
Configuration Config = WebConfigurationManager.OpenWebConfiguration("~");
Config.AppSettings.Settings.Add("SomeKey", "SomeValue");
Config.Save();
return View();
}
public ActionResult About()
{
HttpRuntime.Cache[MESSAGE] = "This is pulled from the HttpRuntime.Cache";
return View();
}
}
}
然后按照以下步骤
- 操作 :应用程序处于调试模式。
- 单击“关于”链接。这会将字符串加载到缓存中。
- 单击“主页”链接。字符串从缓存中取出并保存在 ViewMessage 字典中。一些键/值对被写入 web.config 并保存。缓存中的字符串应出现在主页上。
- 再次单击“主页”链接。字符串应该从缓存中提取,但事实并非如此。
- 停止程序。注释掉以“Config”开头的 3 行。重新启动程序。
- 再次尝试步骤 1 至 4。请注意 HttpRuntime.Cache 尚未清空。
很奇怪吧?
Recently, I've been experimenting with caching objects with HttpRuntime.Cache
and I was generally under the impression that if I "added" something to the cache like this:
HttpRuntime.Cache.Insert("Test", "This is a test!", null,
Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration,
CacheItemPriority.NotRemovable, new CacheItemRemovedCallback(FileChanged));
that the "NotRemovable" and "NoExpiration" flags would keep the object in-memory for the duration of the application. But was finding that at the end of certain page requests, the HttpRuntime.Cache would be completely empty!
Tracing thru and setting a breakpoint inside my Callback "FileChanged" I could see that indeed something was "removing" my object (and every other object in the cache), but I couldn't figure out why. So eventually, I started disabling other things that I thought might affect this subsystem.
Eventually, I commented out the line:
WebConfigurationManager.OpenWebConfiguration("~").Save;
I had been mostly retrieving data from "web.config" in the AppSettings region, but occasionally writing back to AppSettings and saving the changes using the above command. I knew from reading that the "web.config" is cached, but saving my changes back to it shouldn't flush all of HttpRuntime.Cache, right?
Is this a bug? Or are the two caches somehow linked in a way that I should be made aware of?
EDIT:
Ok, I've made this super reproducible if anyone wants to try this on their own machine. (I'm running VS2008 Pro w/ MVC2 targeting .NET 3.5) Just start up a new MVC2 project and paste the following into the HomeController
over whatever is already there:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Configuration;
using System.Configuration;
namespace BackButtonTest.Controllers
{
[HandleError]
public class HomeController : Controller
{
private string MESSAGE = "Message";
public ActionResult Index()
{
ViewData[MESSAGE] = HttpRuntime.Cache.Get(MESSAGE);
Configuration Config = WebConfigurationManager.OpenWebConfiguration("~");
Config.AppSettings.Settings.Add("SomeKey", "SomeValue");
Config.Save();
return View();
}
public ActionResult About()
{
HttpRuntime.Cache[MESSAGE] = "This is pulled from the HttpRuntime.Cache";
return View();
}
}
}
Then follow these steps:
- Start-up the app in debug mode.
- Click on the "About" link. This loads a string into the Cache.
- Click on the "Home" link. String is pulled from the Cache and stuck in ViewMessage dictionary. Some key/value pair is written to web.config and saved. String from cache should appear on the Home page.
- Click on the "Home" link again. String should be pulled from the cache, but it's not.
- Stop program. Comment out the 3 lines that start with "Config". Restart the program.
- Try steps 1 thru 4 again. Notice how the HttpRuntime.Cache has not been emptied.
Weird, huh?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
写入 web.config 将强制应用程序重新启动,并且很可能清空缓存、进程内会话状态等事件将会发生。尝试在 global.asax Application_End 中写下一些日志(或任何方法的名称:))
Writing to your web.config will force the application to restart, and, most likely, events for emptying the cache, in-proc sessionstate etc. will go off. Try and write down some log in global.asax Application_End (or whatever the name of the method is :) )