76 votes

ConfigurationManager.AppSettings [Key] lit-il à partir du fichier web.config à chaque fois?

Je me demande comment le ConfigurationManager.AppSettings[Key] œuvres?

Est-il de lire à partir du fichier physique chaque fois que j'ai besoin d'une clé?

Si oui, dois-je être la lecture de tous les paramètres de l'application de mon web.config dans un cache, puis de les lire?

Ou ASP.NET ou IIS charges sur le web.fichier de configuration à application_startup et une seule fois.

Comment vérifier si le fichier est accessible en lecture de chaque?

Si je change le web.config, IIS redémarre mon application ne peut donc pas vérifier de cette façon.

Merci,

95voto

dash Points 22583

Elle obtient mis en cache, lors du premier accès à un bien, afin de ne pas lire à partir du fichier physique chaque fois que vous demandez une valeur. C'est pourquoi il est nécessaire de redémarrer une application Windows (ou d'Actualisation de la configuration) pour obtenir la dernière valeur, et pourquoi une ASP.Net application redémarre automatiquement lorsque vous modifiez le web.config. Pourquoi ASP.Net est câblé pour redémarrer est discuté dans les références dans la réponse Comment éviter les ASP.NET redémarrage de l'application lorsque le web.la config est modifié.

Nous pouvons le vérifier à l'aide de ILSpy et à la recherche sur le fonctionnement interne du Système.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;
    }
}

Au premier abord, cela semble en effet comme il obtiendra la section à chaque fois. En regardant GetSection:

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

L'essentiel ici est l' PrepareConfigSystem() méthode; ce initialise une instance de l' IInternalConfigSystem domaine détenus par le ConfigurationManager - le type de béton est ClientConfigurationSystem

Dans le cadre de cette charge, une instance de la Configuration de la classe est instanciée. Cette classe est effectivement un objet de représentation du fichier de config, et semble être tenu par le ClientConfigurationSystem de ClientConfigurationHost propriété dans un champ statique - d'où il est mis en cache.

Vous avez pu tester empiriquement en procédant de la manière suivante (dans un Formulaire Windows ou une application WPF):

  1. Départ de votre Application
  2. Accéder à une valeur dans l'app.config
  3. Faites un changement à l'application.config
  4. Vérifiez pour voir si la nouvelle valeur est présente
  5. Appelez ConfigurationManager.RefreshSection("appSettings")
  6. Vérifiez pour voir si la nouvelle valeur est présente.

En fait, j'aurais pu éviter quelques temps, si je venais de lire le commentaire sur le RefreshSection méthode :-)

/// <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>

8voto

Belogix Points 4785

La réponse simple est non, il n'est pas toujours le lire à partir du fichier. Comme certains l'ont suggéré que si le fichier est modifié alors IIS effectue un redémarrage, mais pas toujours! Si vous voulez vous assurer que vous êtes la lecture de la dernière valeur dans le fichier et ne le cache, vous devez appeler quelque chose comme ceci:

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

Et un exemple que j'utilise dans mon code:

/// ======================================================================================
/// <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;
}

Cela vous permet de très facilement choisir (et lors de la lecture de code voir) si vous êtes à l'obtention de la dernière valeur à chaque fois ou si vous ne comptez pas sur la valeur à modifier à partir de quand l'application démarre.

1voto

The Light Points 5726
 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;
 

Tous affichent le même LastAccessTime, ce qui signifie qu'il est mis en cache au démarrage.

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

        DateTime fourth = file.LastAccessTime;
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X