From c353ae645b800cec432c285373daff543fa5af54 Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Fri, 2 Aug 2024 17:03:23 +0800 Subject: [PATCH] =?UTF-8?q?dbcontext=20=E4=B8=8A=E4=B8=8B=E6=96=87?= =?UTF-8?q?=E6=B1=A0=EF=BC=8C=E6=8F=90=E9=AB=98=E6=80=A7=E8=83=BD=E6=B5=8B?= =?UTF-8?q?=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs | 4 +- IRC.Core.SCP/HostConfig/EFSetup.cs | 27 +++++++++--- .../_ServiceExtensions/AutofacModuleSetup.cs | 4 +- IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs | 29 +++++++++++-- .../Context/IRaCISDBContext.cs | 41 +++++++++++-------- 5 files changed, 75 insertions(+), 30 deletions(-) diff --git a/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs b/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs index 6567c9735..629cf9636 100644 --- a/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs +++ b/IRC.Core.SCP/HostConfig/AutofacModuleSetup.cs @@ -45,8 +45,8 @@ namespace IRaCIS.Core.SCP .PropertiesAutowired().AsImplementedInterfaces(); - containerBuilder.RegisterType().As().SingleInstance(); - containerBuilder.RegisterType().As().InstancePerLifetimeScope(); + //containerBuilder.RegisterType().As().SingleInstance(); + //containerBuilder.RegisterType().As().InstancePerLifetimeScope(); diff --git a/IRC.Core.SCP/HostConfig/EFSetup.cs b/IRC.Core.SCP/HostConfig/EFSetup.cs index b53095cbd..77d9465c8 100644 --- a/IRC.Core.SCP/HostConfig/EFSetup.cs +++ b/IRC.Core.SCP/HostConfig/EFSetup.cs @@ -1,4 +1,6 @@ -using IRaCIS.Core.Infra.EFCore; +using EntityFramework.Exceptions.SqlServer; +using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infra.EFCore; using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; @@ -11,15 +13,25 @@ namespace IRaCIS.Core.SCP { public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration) { - //services.AddScoped(); + services.AddHttpContextAccessor(); + services.AddScoped(); + //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 - services.AddDbContext(options => + services.AddPooledDbContextFactory(options => { - options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, + // 在控制台 + //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); + var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); }); + + options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); + options.UseLoggerFactory(logFactory); + + options.UseExceptionProcessor(); + options.EnableSensitiveDataLogging(); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); @@ -30,6 +42,12 @@ namespace IRaCIS.Core.SCP }); + // Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above, + services.AddScoped(); + + // Finally, arrange for a context to get injected from our Scoped factory: + services.AddScoped(sp => sp.GetRequiredService().CreateDbContext()); + //注意区分 easy caching 也有 IDistributedLockProvider services.AddSingleton(sp => { @@ -38,7 +56,6 @@ namespace IRaCIS.Core.SCP return new SqlDistributedSynchronizationProvider(configuration.GetSection("ConnectionStrings:RemoteNew").Value); }); - //services.AddAssemblyTriggers(typeof(SubjectVisitImageDateTrigger).Assembly); } } } diff --git a/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs index 015405bf1..3806353b2 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/AutofacModuleSetup.cs @@ -55,8 +55,8 @@ namespace IRaCIS.Core.API - containerBuilder.RegisterType().As().SingleInstance(); - containerBuilder.RegisterType().As().InstancePerLifetimeScope(); + //containerBuilder.RegisterType().As().SingleInstance(); + //containerBuilder.RegisterType().As().InstancePerLifetimeScope(); //注册hangfire任务 依赖注入 diff --git a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs index 1f4ca4079..17aa20a19 100644 --- a/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs +++ b/IRaCIS.Core.API/_ServiceExtensions/EFSetup.cs @@ -1,11 +1,15 @@ -using Hangfire.SqlServer; +using Castle.Core.Logging; +using EntityFramework.Exceptions.SqlServer; +using Hangfire.SqlServer; using IRaCIS.Core.Application.Triggers; +using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infra.EFCore; using Medallion.Threading; using Medallion.Threading.SqlServer; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using StackExchange.Redis; namespace IRaCIS.Core.API @@ -14,15 +18,28 @@ namespace IRaCIS.Core.API { public static void AddEFSetup( this IServiceCollection services, IConfiguration configuration) { - //services.AddScoped(); + + services.AddHttpContextAccessor(); + services.AddScoped(); + + // First, register a pooling context factory as a Singleton service, as usual: //这个注入没有成功--注入是没问题的,构造函数也只是支持参数就好,错在注入的地方不能写DbContext //Web程序中通过重用池中DbContext实例可提高高并发场景下的吞吐量, 这在概念上类似于ADO.NET Provider原生的连接池操作方式,具有节省DbContext实例化成本的优点 - services.AddDbContext(options => + services.AddPooledDbContextFactory(options => { + + // 在控制台 + //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); + var logFactory = LoggerFactory.Create(builder => { builder.AddDebug(); }); + options.UseSqlServer(configuration.GetSection("ConnectionStrings:RemoteNew").Value, contextOptionsBuilder => contextOptionsBuilder.EnableRetryOnFailure()); + options.UseLoggerFactory(logFactory); + + options.UseExceptionProcessor(); + options.EnableSensitiveDataLogging(); options.AddInterceptors(new QueryWithNoLockDbCommandInterceptor()); @@ -62,6 +79,12 @@ namespace IRaCIS.Core.API }); + // Register an additional context factory as a Scoped service, which gets a pooled context from the Singleton factory we registered above, + services.AddScoped(); + + // Finally, arrange for a context to get injected from our Scoped factory: + services.AddScoped(sp => sp.GetRequiredService().CreateDbContext()); + //注意区分 easy caching 也有 IDistributedLockProvider services.AddSingleton(sp => { diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index f81edd5f5..0644e35c3 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -24,33 +24,38 @@ using IRaCIS.Core.Infrastructure; namespace IRaCIS.Core.Infra.EFCore { + + public class IRaCISDBScopedFactory : IDbContextFactory + { + + private readonly IDbContextFactory _pooledFactory; + private readonly IUserInfo _userInfo; + + public IRaCISDBScopedFactory(IDbContextFactory pooledFactory,IUserInfo userInfo) + { + _pooledFactory = pooledFactory; + _userInfo = userInfo; + } + + public IRaCISDBContext CreateDbContext() + { + var context = _pooledFactory.CreateDbContext(); + context._userInfo = _userInfo; + return context; + } + } + public class IRaCISDBContext : DbContext { - public readonly IUserInfo _userInfo; + public IUserInfo _userInfo; public readonly ILogger _logger; - // 在控制台 - //public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddConsole(); }); - // 调试窗口 - public static readonly ILoggerFactory MyLoggerFactory = LoggerFactory.Create(builder => { builder.AddDebug(); }); - public IRaCISDBContext(DbContextOptions options, IUserInfo userInfo, ILogger logger + public IRaCISDBContext(DbContextOptions options, ILogger logger ) : base(options) { _logger= logger; - _userInfo = userInfo; - - } - - - //比数据库上下文构造函数先执行 不能构造函数注入的方式使用配置文件 - protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) - { - optionsBuilder.UseLoggerFactory(MyLoggerFactory); - - optionsBuilder.UseExceptionProcessor(); - }