2012-11-13 25 views
64

我只是想知道ConfigurationManager.AppSettings [Key]是如何工作的?ConfigurationManager.AppSettings [Key]每次都从web.config文件读取?

每次我需要钥匙时,它是否从物理文件中读取?

如果是这样,我应该读取我的web.config的所有应用程序设置缓存中,然后从中读取?

或者ASP.NET或IIS将web.config文件加载到application_startup并且只加载一次。

如何验证每次读取是否访问物理文件?

如果我更改web.config,IIS会重新启动我的应用程序,因此无法以此方式验证它。

感谢,

回答

78

它缓存,在性能的第一次访问,所以它不会从物理文件中的每个你问一个值时读取。这就是为什么有必要重新启动Windows应用程序(或配置Refresh)以获取最新值,以及为什么在编辑web.config时ASP.Net应用程序会自动重新启动。为什么ASP.Net硬连线重启在回答How to prevent an ASP.NET application restarting when the web.config is modified的参考文献中讨论。

我们可以验证这一点使用ILSpy,看着System.Configuration的内部结构:

public static NameValueCollection AppSettings 
{ 
    get 
    { 
     object section = ConfigurationManager.GetSection("appSettings"); 
     if (section == null || !(section is NameValueCollection)) 
     { 
      throw new ConfigurationErrorsException(SR.GetString("Config_appsettings_declaration_invalid")); 
     } 
     return (NameValueCollection)section; 
    } 
} 

起初,这确实像它每次都会得到部分。看GetSection:

public static object GetSection(string sectionName) 
{ 
    if (string.IsNullOrEmpty(sectionName)) 
    { 
     return null; 
    } 
    ConfigurationManager.PrepareConfigSystem(); 
    return ConfigurationManager.s_configSystem.GetSection(sectionName); 
} 

这里的关键线是PrepareConfigSystem()方法;这将初始化由ConfigurationManager持有的IInternalConfigSystem字段的一个实例 - 具体类型为ClientConfigurationSystem

作为此加载的一部分,将实例化Configuration类的实例。该类实际上是配置文件的对象表示,并且似乎由ClientConfigurationSystem的ClientConfigurationHost属性在静态字段中保存 - 因此它被缓存。

你可以做实证检验此以下(在Windows窗体或WPF应用程序):

  1. 启动您的应用程式上
  2. 访问的app.config
  3. 的值进行更改,以App.Config中
  4. 查看一下新的值是否存在
  5. 呼叫ConfigurationManager.RefreshSection("appSettings")
  6. 检查,看是否新的值存在。

其实,我可以救自己一些时间,如果我刚刚看了评论的RefreshSection方法:-)

/// <summary>Refreshes the named section so the next time that it is retrieved it will be re-read from disk.</summary> 
/// <param name="sectionName">The configuration section name or the configuration path and section name of the section to refresh.</param> 
1
var file = 
      new FileInfo(@"\\MyConfigFilePath\Web.config"); 

     DateTime first = file.LastAccessTime; 

     string fn = ConfigurationManager.AppSettings["FirstName"]; 
     Thread.Sleep(2000); 

     DateTime second = file.LastAccessTime; 

     string sn = ConfigurationManager.AppSettings["Surname"]; 
     Thread.Sleep(2000); 

     DateTime third = file.LastAccessTime; 

所有显示相同的LastAccessTime这意味着它的缓存在启动时。

 string fn1 = ConfigurationManager.AppSettings["FirstName"]; 
     Thread.Sleep(2000); 

     DateTime fourth = file.LastAccessTime; 
7

简单的答案是否定的,它并不总是从文件中读取它。正如一些人建议如果文件被更改,然后IIS执行重新启动,但并不总是!如果你想保证你正在阅读该文件中的最新值,而不是你需要调用这样的高速缓存:

ConfigurationManager.RefreshSection("appSettings"); 
string fromFile = ConfigurationManager.AppSettings.Get(key) ?? string.Empty; 

而且一个例子,我在我的代码中使用:

/// ====================================================================================== 
/// <summary> 
/// Refreshes the settings from disk and returns the specific setting so guarantees the 
/// value is up to date at the expense of disk I/O. 
/// </summary> 
/// <param name="key">The setting key to return.</param> 
/// <remarks>This method does involve disk I/O so should not be used in loops etc.</remarks> 
/// <returns>The setting value or an empty string if not found.</returns> 
/// ====================================================================================== 
private string RefreshFromDiskAndGetSetting(string key) 
{ 
    // Always read from the disk to get the latest setting, this will add some overhead but 
    // because this is done so infrequently it shouldn't cause any real performance issues 
    ConfigurationManager.RefreshSection("appSettings"); 
    return GetCachedSetting(key); 
} 

/// ====================================================================================== 
/// <summary> 
/// Retrieves the setting from cache so CANNOT guarantees the value is up to date but 
/// does not involve disk I/O so can be called frequently. 
/// </summary> 
/// <param name="key">The setting key to return.</param> 
/// <remarks>This method cannot guarantee the setting is up to date.</remarks> 
/// <returns>The setting value or an empty string if not found.</returns> 
/// ====================================================================================== 
private string GetCachedSetting(string key) 
{ 
    return ConfigurationManager.AppSettings.Get(key) ?? string.Empty; 
} 

这使您可以非常容易地选择(以及在阅读代码时看到)每次获取最新值还是希望应用程序启动时值不会改变。

+1

你是什么意思的“不总是”!这是设计我已经理解,IIS重新启动应用程序并重新加载配置。 –

相关问题