net core Scoped Service inside Singleton Service 解决方案

首先,我们先分析一下为什么会出现这个问题

原因:singleton Service 无法直接或间接的注入Scoped Service 

为什么会有这种问题呢

原因:singleton Service 是单例的,也就是说在整个应用程序中只会存在同种类型的唯一的实例,这就意味着,一旦实例被创建,所有的注入都已经固定化,他所依赖的其他服务也就只会存在一个实例。

Scoped Service 的生命周期很短,当会话结束时,实例也就被释放,所以当在singleton Service 中注入 Scoped Service 是不被允许的,同理 Transient也是不被允许的。

搞清楚这点,剩下的事情就好解决了。

我们如何在 Singleton Service 中使用 Scoped Service 或者 Transient Service 呢?

其实很简单,我们只需要在 Singleton Service 中创建会话即可,这样的话在会话中去创建  Scoped Service和 Transient Service 的实例就OK了

咱直接用示例来进行讲解

上代码

using EFCoreDemo.Models;
using EFCoreDemo.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace EFCoreDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddDbContext<SchoolContext>(option =>
                    {
                        option.UseSqlServer(hostContext.Configuration.GetConnectionString("Main"));
                    });

                    services.AddTransient<ITeacherService, TeacherService>();
                    services.AddHostedService<Worker>();
                });
    }
}
using EFCoreDemo.Models;
using EFCoreDemo.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace EFCoreDemo
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;
        private readonly IServiceScopeFactory _scopeFactory;
        public Worker(ILogger<Worker> logger, IServiceScopeFactory scopeFactory)
        {
            _logger = logger;
            _scopeFactory = scopeFactory;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                using (var scope = _scopeFactory.CreateScope())
                {
                    var _teacherService = scope.ServiceProvider.GetRequiredService<ITeacherService>();
                    _teacherService.AddTeacher(new Teacher
                    {
                        Salary = 20000,
                        Age = 30,
                        CreateTime = DateTime.Now,
                        InductionTime = DateTime.Now.AddYears(-10),
                        IsDetele = false,
                        IsMarried = true,
                        Job = "语文老师",
                        Name = "张珊",
                        UpdateTime = DateTime.Now
                    });
                }


                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

我们来解释一下上面的代码

首先 这个是一个自定义的托管程序,我们通过 services.AddHostedService<Worker>(); 注入我们的托管服务 众所周知 HostedService 是单例的

然后我们又通过AddDbContext方法将我们的数据库上下文进行注入,而数据库上下文又是scoped的 

最后我们还注入了我们自己定义的瞬时服务 services.AddTransient<ITeacherService, TeacherService>();

在worker中 我们注入了 IServiceScopeFactory 对象,这个对象是netcore框架中自带的,用于创建会话

在 worker的具体执行方法中我们每隔1秒钟创建一次会话,这样的话我们就搭建了 使用 ITeacherService 的基础,也就是 每一秒都会产生一个 ITeacherService服务的示例 在这个会话中 数据库上下文只会存在一个实例,会话结束即释放

这就完成了我们再 单例模式中使用会话模式服务的目的。

就是这么简单。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值