ConfigurationManager。AppSettings[键]从网络中读取。配置文件每一次?

时间:2023-02-12 01:51:54

I'm just wondering how the ConfigurationManager.AppSettings[Key] works?

我只是想知道配置管理器。AppSettings(例子)作品吗?

Does it read from the physical file each time I need a key?

每次我需要一个键时,它是否从物理文件读取?

If so, should I be reading all the app settings of my web.config in a cache and then read from it?

如果是的话,我应该阅读我网站上所有的应用设置。在缓存中配置然后从中读取?

Or ASP.NET or IIS loads the web.config file at application_startup and only once.

或ASP。NET或IIS加载web。在application_startup中配置文件,仅一次。

How to verify whether the physical file is accessed by each read?

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

If I change the web.config, IIS restarts my application so can't verify it that way.

如果我改变了网络。配置,IIS重新启动我的应用程序,所以不能这样验证它。

Thanks,

谢谢,

3 个解决方案

#1


79  

It gets cached, on first access of a property, so it does not read from the physical file each time you ask for a value. This is why it is necessary to restart an Windows app (or Refresh the config) to get the latest value, and why an ASP.Net app automatically restarts when you edit web.config. Why ASP.Net is hard wired to restart is discussed in the references in the answer How to prevent an ASP.NET application restarting when the web.config is modified.

它在第一次访问属性时被缓存,因此在每次请求值时它不会从物理文件中读取。这就是为什么需要重新启动Windows应用程序(或刷新配置)来获取最新值,以及为什么要使用ASP。当你编辑web.config时,Net应用程序会自动重新启动。为什么ASP。在回答如何防止ASP时,在参考文献中讨论了重新启动的硬连接网络。NET应用程序在web上重新启动。配置修改。

We can verify this using ILSpy and looking at the internals of System.Configuration:

我们可以使用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;
    }
}

At first, this does indeed look like it will get the section every time. Looking at GetSection:

一开始,它看起来确实每次都会得到这个部分。看着GetSection:

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

The critical line here is the PrepareConfigSystem() method; this initializes an instance of the IInternalConfigSystem field held by the ConfigurationManager - the concrete type is ClientConfigurationSystem

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

As part of this load, an instance of the Configuration class is instantiated. This class is effectively an object representation of the config file, and appears to be held by the ClientConfigurationSystem's ClientConfigurationHost property in a static field - hence it is cached.

作为这个负载的一部分,配置类的一个实例被实例化。这个类实际上是配置文件的对象表示形式,并且看起来是由ClientConfigurationSystem的ClientConfigurationHost属性在静态字段中保存的—因此它被缓存。

You could test this empirically by doing the following (in a Windows Form or WPF app):

您可以通过以下操作(在Windows窗体或WPF应用程序中)进行经验测试:

  1. Starting your App up
  2. 开始你的应用程序
  3. Access a value in app.config
  4. 在app.config中访问一个值
  5. Make a change to app.config
  6. 更改app.config
  7. Check to see whether the new value is present
  8. 检查新值是否存在
  9. Call ConfigurationManager.RefreshSection("appSettings")
  10. 调用ConfigurationManager.RefreshSection(“appSettings”)
  11. Check to see if the new value is present.
  12. 检查新值是否存在。

In fact, I could have saved myself some time if I'd just read the comment on the RefreshSection method :-)

事实上,如果我读一下关于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>

#2


7  

The simple answer is no, it doesn't always read it from the file. As some have suggested if the file is changed then IIS performs a restart but not always! If you want to guarantee that you are reading the very latest value from the file and not the cache you need to call something like this:

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

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

And an example I use in my 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;
}

This allows you to very easily choose (and when reading code see) whether you are getting the latest value each time or if you don't expect the value to change from when the application starts.

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

#3


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;

All show the same LastAccessTime which means it's cached at startup.

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

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

        DateTime fourth = file.LastAccessTime;

#1


79  

It gets cached, on first access of a property, so it does not read from the physical file each time you ask for a value. This is why it is necessary to restart an Windows app (or Refresh the config) to get the latest value, and why an ASP.Net app automatically restarts when you edit web.config. Why ASP.Net is hard wired to restart is discussed in the references in the answer How to prevent an ASP.NET application restarting when the web.config is modified.

它在第一次访问属性时被缓存,因此在每次请求值时它不会从物理文件中读取。这就是为什么需要重新启动Windows应用程序(或刷新配置)来获取最新值,以及为什么要使用ASP。当你编辑web.config时,Net应用程序会自动重新启动。为什么ASP。在回答如何防止ASP时,在参考文献中讨论了重新启动的硬连接网络。NET应用程序在web上重新启动。配置修改。

We can verify this using ILSpy and looking at the internals of System.Configuration:

我们可以使用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;
    }
}

At first, this does indeed look like it will get the section every time. Looking at GetSection:

一开始,它看起来确实每次都会得到这个部分。看着GetSection:

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

The critical line here is the PrepareConfigSystem() method; this initializes an instance of the IInternalConfigSystem field held by the ConfigurationManager - the concrete type is ClientConfigurationSystem

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

As part of this load, an instance of the Configuration class is instantiated. This class is effectively an object representation of the config file, and appears to be held by the ClientConfigurationSystem's ClientConfigurationHost property in a static field - hence it is cached.

作为这个负载的一部分,配置类的一个实例被实例化。这个类实际上是配置文件的对象表示形式,并且看起来是由ClientConfigurationSystem的ClientConfigurationHost属性在静态字段中保存的—因此它被缓存。

You could test this empirically by doing the following (in a Windows Form or WPF app):

您可以通过以下操作(在Windows窗体或WPF应用程序中)进行经验测试:

  1. Starting your App up
  2. 开始你的应用程序
  3. Access a value in app.config
  4. 在app.config中访问一个值
  5. Make a change to app.config
  6. 更改app.config
  7. Check to see whether the new value is present
  8. 检查新值是否存在
  9. Call ConfigurationManager.RefreshSection("appSettings")
  10. 调用ConfigurationManager.RefreshSection(“appSettings”)
  11. Check to see if the new value is present.
  12. 检查新值是否存在。

In fact, I could have saved myself some time if I'd just read the comment on the RefreshSection method :-)

事实上,如果我读一下关于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>

#2


7  

The simple answer is no, it doesn't always read it from the file. As some have suggested if the file is changed then IIS performs a restart but not always! If you want to guarantee that you are reading the very latest value from the file and not the cache you need to call something like this:

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

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

And an example I use in my 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;
}

This allows you to very easily choose (and when reading code see) whether you are getting the latest value each time or if you don't expect the value to change from when the application starts.

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

#3


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;

All show the same LastAccessTime which means it's cached at startup.

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

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

        DateTime fourth = file.LastAccessTime;