- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我编写了一个自定义配置提供程序,按照此处的说明从数据库表加载 ASP.NET Core 配置:
ASP.Net Custom Configuration Provider
我的提供商使用 SqlDependency
如果数据库中的值发生更改,则重新加载配置。
documentation对于 SqlDependency
指出:
The Stop method must be called for each Start call. A given listener only shuts down fully when it receives the same number of Stop requests as Start requests.
我不确定如何在 ASP.NET Core 的自定义配置提供程序中执行此操作。
我们来看看代码:
DbConfigurationSource
基本上是 IDbProvider
的容器,用于处理从数据库检索数据
public class DbConfigurationSource : IConfigurationSource
{
/// <summary>
/// Used to access the contents of the file.
/// </summary>
public virtual IDbProvider DbProvider { get; set; }
/// <summary>
/// Determines whether the source will be loaded if the underlying data changes.
/// </summary>
public virtual bool ReloadOnChange { get; set; }
/// <summary>
/// Will be called if an uncaught exception occurs in FileConfigurationProvider.Load.
/// </summary>
public Action<DbLoadExceptionContext> OnLoadException { get; set; }
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new DbConfigurationProvider(this);
}
}
DbConfigurationDataProvider
该类创建并监视 SqlDependency
并从数据库加载数据。这也是我想要 Stop()
SqlDependency
调用 Dispose()
的地方。当前未调用 Dispose()
。
public class DbConfigurationDataProvider : IDbProvider, IDisposable
{
private readonly string _applicationName;
private readonly string _connectionString;
private ConfigurationReloadToken _reloadToken;
public DbConfigurationDataProvider(string applicationName, string connectionString)
{
if (string.IsNullOrWhiteSpace(applicationName))
{
throw new ArgumentNullException(nameof(applicationName));
}
if (string.IsNullOrWhiteSpace(connectionString))
{
throw new ArgumentNullException(nameof(connectionString));
}
_applicationName = applicationName;
_connectionString = connectionString;
_reloadToken = new ConfigurationReloadToken();
SqlDependency.Start(_connectionString);
}
void OnDependencyChange(object sender, SqlNotificationEventArgs e)
{
var dependency = (SqlDependency)sender;
dependency.OnChange -= OnDependencyChange;
var previousToken = Interlocked.Exchange(
ref _reloadToken,
new ConfigurationReloadToken());
previousToken.OnReload();
}
public IChangeToken Watch()
{
return _reloadToken;
}
public List<ApplicationSettingDto> GetData()
{
var settings = new List<ApplicationSettingDto>();
var sql = "select parameter, value from dbo.settingsTable where application = @application";
using (var connection = new SqlConnection(_connectionString))
{
using (var command = new SqlCommand(sql, connection))
{
command.Parameters.AddWithValue("application", _applicationName);
var dependency = new SqlDependency(command);
// Subscribe to the SqlDependency event.
dependency.OnChange += OnDependencyChange;
connection.Open();
using (var reader = command.ExecuteReader())
{
var keyIndex = reader.GetOrdinal("parameter");
var valueIndex = reader.GetOrdinal("value");
while (reader.Read())
{
settings.Add(new ApplicationSettingDto
{Key = reader.GetString(keyIndex), Value = reader.GetString(valueIndex)});
}
}
}
}
Debug.WriteLine($"{DateTime.Now}: {settings.Count} settings loaded");
return settings;
}
public void Dispose()
{
SqlDependency.Stop(_connectionString);
Debug.WriteLine($"{nameof(WhsConfigurationProvider)} Disposed");
}
}
DbConfigurationProvider
此类监视 DbConfigurationDataProvider
中的 changeToken
并将新配置发布到应用程序。
public class DbConfigurationProvider : ConfigurationProvider
{
private DbConfigurationSource Source { get; }
public DbConfigurationProvider(DbConfigurationSource source)
{
Source = source ?? throw new ArgumentNullException(nameof(source));
if (Source.ReloadOnChange && Source.DbProvider != null)
{
ChangeToken.OnChange(
() => Source.DbProvider.Watch(),
() =>
{
Load(reload: true);
});
}
}
private void Load(bool reload)
{
// Always create new Data on reload to drop old keys
if (reload)
{
Data = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
var settings = Source.DbProvider.GetData();
try
{
Load(settings);
}
catch (Exception e)
{
HandleException(e);
}
OnReload();
}
public override void Load()
{
Load(reload: false);
}
public void Load(List<ApplicationSettingDto> settings)
{
Data = settings.ToDictionary(s => s.Key, s => s.Value, StringComparer.OrdinalIgnoreCase);
}
private void HandleException(Exception e)
{
// Removed for brevity
}
}
DbConfigurationExtensions
调用扩展方法来设置一切。
public static class DbConfigurationExtensions
{
public static IConfigurationBuilder AddDbConfiguration(this IConfigurationBuilder builder, IConfiguration config, string applicationName = "")
{
if (string.IsNullOrWhiteSpace(applicationName))
{
applicationName = config.GetValue<string>("ApplicationName");
}
// DB Server and Catalog loaded from Environment Variables for now
var server = config.GetValue<string>("DbConfigurationServer");
var database = config.GetValue<string>("DbConfigurationDatabase");
if (string.IsNullOrWhiteSpace(server))
{
// Removed for brevity
}
if (string.IsNullOrWhiteSpace(database))
{
// Removed for brevity
}
var sqlBuilder = new SqlConnectionStringBuilder
{
DataSource = server,
InitialCatalog = database,
IntegratedSecurity = true
};
return builder.Add(new DbConfigurationSource
{
DbProvider = new DbConfigurationDataProvider(applicationName, sqlBuilder.ToString()),
ReloadOnChange = true
} );
}
}
最后,调用来设置整个事情:
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddDbConfiguration(hostingContext.Configuration, "TestApp");
}).UseStartup<Startup>();
}
总结一下:如何确保在 DbConfigurationDataProvider
类中调用 Dispose()
方法?
到目前为止我找到的唯一信息来自这里: https://andrewlock.net/four-ways-to-dispose-idisposables-in-asp-net-core/
其中涵盖了如何处置对象:
选项 4 如下所示:
public void Configure(IApplicationBuilder app, IApplicationLifetime applicationLifetime,
SingletonAddedManually toDispose)
{
applicationLifetime.ApplicationStopping.Register(OnShutdown, toDispose);
// configure middleware etc
}
private void OnShutdown(object toDispose)
{
((IDisposable)toDispose).Dispose();
}
SingletonAddedManually
在我的例子中将是 DbConfigurationDataProvider
类,但这远远超出了 Startup
类的范围。
有关 IApplicationLifetime
接口(interface)的更多信息:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-2.2
编辑
这个例子甚至没有调用SqlDependency.Stop()
,也许它并不那么重要?
https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/sqldependency-in-an-aspnet-app
最佳答案
执行此操作的“正确”方法是让您的配置提供程序是一次性的,然后将所有 SqlDependency
对象作为配置提供程序处置的一部分进行处置。
不幸的是,在 2.x 中,配置框架不支持一次性提供程序。然而,作为 aspnet/Extensions#786 的一部分,这可能会发生变化。和 aspnet/Extensions#861 .
由于我参与了此开发,我可以自豪地宣布从 3.0 开始,将支持一次性配置提供程序。
使用 Microsoft.Extensions.Configuration
3.0,当配置根被处置时,一次性提供程序将被正确处置。当(Web)主机被释放时,配置根将在 ASP.NET Core 3.0 中被释放。因此,最终,您的一次性配置提供程序将被正确处理,并且不应再泄漏任何内容。
关于c# - 停止自定义 ASP.NET Core 配置提供程序中的 SqlDependency,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54072129/
我正在使用 Tkinter 在 python 上写一个小游戏(顺便说一下,我不允许使用任何其他非内置模块)并且我想在主窗口上播放背景歌曲,这是那个包含标题,以及转到其他窗口和内容的按钮... 所以问题
我有一个 Azure WebJob,它在一个非常简单的应用服务标准:1 Small(计划)上运行。 现在,我的 WebJob(有 5 个函数正在运行)出现问题 - 我想停止 5 个正在运行的函数中的
我在 MacOS Lion 上使用 XCode 4.2。在模拟器中调试 iPhone/iPad 应用程序时,我使用 XCode 工具栏上的“停止”按钮(产品 | 停止)退出应用程序。在此之后,XCod
我刚刚下载了android开放源代码项目,并尝试使用make来构建它,我收到了以下消息: build/core/prebuilt.mk:91: *** recipe commences before
我以前从未制作过 makefile,但我们已经收到了这个,但是,如果我尝试运行它,它只会说, missing separator. stop. 我不知道可能出了什么问题 - 我已经确保空格只按制表符。
好吧,这段代码非常基本。用户将答案输入文本框,如果等于“第一+第二”,他们就得到一分。然后,他们有 5 秒钟的时间回答下一个数学问题。如果他们这样做了,函数“doCalculation”将再次运行,他
我在 viewController 中有一个循环动画 - (void)moveAnimating { [UIView animateWithDuration:2.0f animations:^
当我有一个待处理的 ASIFormDataRequest(作为异步任务启动)仍在执行并且用户按下后退按钮(为了弹出 View )时,我的 viewController 出现问题。 有什么方法可以停止该
我们正在使用 flashdevelop 和 flash CS 3 开发基于 flash 的游戏。我们正在使用 flash CS3 发布 swc,swc 将作为库在 flashdevlop 中使用。 一
我在线程中有一个连接,因此我将其添加到运行循环中以获取所有数据: [[NSRunLoop currentRunLoop] run]; [connection scheduleInRunLoop
你好,我做了一个 php 套接字服务器来从 plc 获取数据,plc 被配置为 tcp 套接字客户端。 我有一个严重的问题,如果本地网络出现故障,似乎功能 socket_accept 停止,plc 无
这个问题已经有答案了: How to stop a setTimeout loop? (10 个回答) 已关闭 8 年前。 请帮助获得正确的函数或方法来停止 setTimeout 函数。 我一直在尝试
我正在运行一个多项目SBT(v0.13)构建,并且希望它在子项目中遇到的第一个错误(编译)时快速失败(停止)。 当前的行为是,当某项无法在子项目中进行编译时,构建将继续(以编译所有其他子项目)。 一旦
我有播放.wav文件中声音的代码,但是我无法停止播放歌曲,甚至无法退出程序直到播放结束。因为这是一首5分钟的歌曲,所以这是一个问题。这是我如何播放wav的代码: public class EasySo
我正在寻找一种解决方案,该如何控制从JSF应用程序播放音频文件。 我不需要完整的解决方案,只需引用我可以用来控制播放音频文件(开始/停止/更改声音)的组件即可。 我尝试搜索过去的问题,但没有成功。 我
我已经在test.ps1中编写了以下函数,在运行该脚本以启动/停止/ ..时我想做一个选择: function getState($SeviceName) { $server = @('hos
我必须设置一个 10 分钟的计时器,它会重定向到主屏幕。此外,它必须在每个操作(例如按下按钮)时重置。我找到了这个计时器:https://github.com/fengyuanchen/vue-cou
我正在制作一个聊天应用程序,功能之一就是发送声音。发送的HTML如下: LOL Stop Play 第一次发送时,“自动播放”效果很好。因此,现在我
我基本上希望页面能够接受用户输入的时间(以秒为单位)。 之后我希望当用户按下“开始”按钮时开始倒计时按下暂停按钮时“暂停”。还有一个重置按钮,以便用户可以从头开始倒计时。 这是我到目前为止得到的:
我需要停止 $.each 循环,加载图像,然后继续循环。我有 Canvas ,可以在其中加载对象图像。对象以正确的顺序排列在数组中。现在,当我尝试从数组加载对象时,存在一个问题:由于尺寸不同,并且它们
我是一名优秀的程序员,十分优秀!