這個問題在這里已經有了答案: 升級到 ASP.NET Core 2.0 后,無法從單例 IActiveUsersService 使用范圍服務 IMongoDbContext (4 個回答) 無法使用來自單例“Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor”的范圍服務“MyDbContext” (5 個回答) 3 小時前關閉。
我想知道如何IServiceCollection.AddDbContext()添加我的ApplicationDbContext. 我的猜測是它沒有作為單例添加,并且每個請求都會創建一個新實體。
我正在實作一個 custom ILoggerProvider,它需要一個ApplicationDbContext.
我的問題是:如果 myILoggerProvider配置為單例,但它依賴于非單例,會發生什么ApplicationDbContext?
uj5u.com熱心網友回復:
是的,但是使用來自 ILogger 的 DbContext 并不是最好的主意。記錄器和日志接收器是獨立的物體。
從單例中使用范圍服務并不罕見。注冊為單例的后臺服務就是這種情況。在后臺任務中使用范圍服務部分解釋了使用范圍服務。
要使用作用域(或瞬態)服務,單例需要訪問IServiceProvider. 這通常作為建構式依賴項傳遞。
public class MyHostedService : BackgroundService
{
private readonly ILogger<MyHostedService> _logger;
public MyHostedService(IServiceProvider services,
ILogger<MyHostedService> logger)
{
Services = services;
_logger = logger;
}
}
此類可用于使用IServiceProvider.GetService或GetRequiredService檢索瞬態實體:
var service = Services.GetRequiredService<MyTransientService>();
要使用范圍服務,單例需要顯式創建范圍并從該范圍檢索服務。當作用域被釋放時,任何作用域實體也將被釋放
using (var scope = Services.CreateScope())
{
var context =
scope.ServiceProvider
.GetRequiredService<MyDbContext>();
...
context.SaveChanges();
}
記錄器和資料庫
ILogger 不需要依賴于 DbContext。日志庫使用單獨的介面來發布和存盤日志條目。一個ILogger實體用于發布日志條目,而不是存盤。存盤日志事件是日志接收器或日志提供者的作業——不同的日志庫為此使用不同的名稱。
.NET Core 有意提供很少的日志接收器。有非常好的日志庫,如 Serilog,.NET Core 團隊無意重復他們的作業。他們確實為 Azure Application Insights 等 Microsoft 特定服務提供了一些接收器實作。
可以撰寫一個寫入資料庫的自定義日志接收器,但最好使用已經提供此功能并負責緩沖、異步操作等的現有庫。寫入資料庫總是比寫入本地檔案更昂貴,因此資料庫接收器需要緩沖訊息以減少對應用程式的影響。
使用例如Serilog.AspNetCore可以輕松集成現有庫之一,如Serilog。
public static int Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
....
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog() // <-- Add this line
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
該庫反過來提供像Serilog.Sinks.SqlServer這樣的資料庫接收器。
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.MSSqlServer(
connectionString: "Server=localhost;Database=LogDb;Integrated Security=SSPI;",
sinkOptions: new MSSqlServerSinkOptions { TableName = "LogEvents" })
.CreateLogger();
SQL Server 接收器將創建日志表并開始向其中寫入日志條目。該UseSerilog()呼叫會將所有ILogger呼叫重定向到 Serilog,并最終重定向到資料庫表。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/329745.html
上一篇:AgGrid渲染空白
下一篇:模擬存盤庫回傳null
