web-dev-qa-db-ja.com

ConfigurationManager.AppSettings [Key]は毎回web.configファイルから読み取りますか?

ConfigurationManager.AppSettings [Key]がどのように機能するのか疑問に思っていますか?

キーが必要になるたびに物理ファイルから読み取られますか?

その場合、キャッシュ内のweb.configのすべてのアプリ設定を読み取ってから読み取る必要がありますか?

または、ASP.NETまたはIISは、application_startupで一度だけweb.configファイルをロードします。

物理ファイルが読み取りごとにアクセスされるかどうかを確認するにはどうすればよいですか?

Web.configを変更すると、IISはアプリケーションを再起動するため、そのように検証できません。

おかげで、

67
The Light

プロパティへの最初のアクセス時にキャッシュされるため、値を要求するたびに物理ファイルから読み取ることはありません。これが、最新の値を取得するためにWindowsアプリを再起動する(または Refresh config)必要があり、web.configを編集するとASP.Netアプリが自動的に再起動する理由です。 ASP.Netが再起動するように配線されている理由は、答え web.configが変更されたときにASP.NETアプリケーションが再起動するのを防ぐ方法 の参照で説明されています。

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>
_
83
dash

簡単な答えは「いいえ」です。常にファイルから読み取るとは限りません。ファイルが変更された場合、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;
}

これにより、毎回最新の値を取得するか、アプリケーションの起動時から値が変化しないかを非常に簡単に選択できます(コードの読み取り時に参照できます)。

7
Belogix
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;
1
The Light