2012-11-13 55 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重新啓動應用程序並重新加載配置。 –

相關問題