title: How to consume scoped service with dependency in a background task
body: <p>Here is my scenerio. I want to use background task to send newsletter to subscribed users. This is done by MailService, which has UnitOfWork as dependency. </p>
  
  <p>I tried the solution from <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-2.2" rel="noreferrer">docs.microsoft.com</a>
  so in my case I use a method of IMailService instead of ILogger, but I'm getting an error:</p>
  
  <blockquote>
    <p>System.InvalidOperationException: 'Cannot consume scoped service >'Fit4You.Core.Data.IUnitOfWork' from singleton >'Microsoft.AspNetCore.Hosting.Internal.HostedServiceExecutor'.'</p>
  </blockquote>
  
  <p><strong>I don't want to make my UnitOfWork or DbContext with Singleton lifetime.</strong> Is it possible to consume somehow a dependency of MailService which is scoped UnitOfWork?</p>
  
  <p>I know about IServiceScopeFactory but maybe don't know how to use it properly.</p>
  
  <p>I'm using .NET Core 2.2 and build in interface IHostedService</p>
  
  <p>ScopedMailService:</p>
  
  <pre><code>public class ScopedMailService : IScopedMailService
  {
      private readonly IMailService mailService;
  
      public ScopedMailService(IMailService mailService)
      {
          this.mailService = mailService;
      }
  
      public void DoWork()
      {
          mailService.SendNewsletterToSubscribedUsers();
      }
  }
  </code></pre>
  
  <p>ConsumeScopedMailService:</p>
  
  <pre><code>public class ConsumeScopedMailService : IHostedService
  {
      private Timer timer;
      private readonly IMailService mailService;
      public IServiceProvider Services { get; }
  
      public ConsumeScopedMailService(IServiceProvider services, IMailService mailService)
      {
          Services = services;
          this.mailService = mailService;
      }
  
      public Task StartAsync(CancellationToken cancellationToken)
      {
          var startTimeSpan = GetStartTimeSpan();
          var periodTimeSpan = TimeSpan.FromSeconds(30);
  
          timer = new Timer(DoWork, null, startTimeSpan, periodTimeSpan);
  
          return Task.CompletedTask;
      }
  
      private void DoWork(object state)
      {
          using (var scope = Services.CreateScope())
          {
              var scopedMailService = scope.ServiceProvider.GetRequiredService&lt;IScopedMailService&gt;();
              scopedMailService.DoWork();
          }
      }
  
      public Task StopAsync(CancellationToken cancellationToken)
      {
          timer?.Change(Timeout.Infinite, 0);
          return Task.CompletedTask;
      }
  
      public void Dispose()
      {
          timer?.Dispose();
      }
  
      private TimeSpan GetStartTimeSpan()
      {
          var currentTime = DateTime.Now.Ticks;
          var executeTime = DateTime.Today.AddHours(8)
                                          .AddMinutes(0)
                                          .Ticks;
  
          long ticks = executeTime - currentTime;
  
          if (ticks &lt; 0)
          {
              ticks = ticks + TimeSpan.TicksPerDay;
          }
  
          var startTimeSpan = new TimeSpan(ticks);
  
          return startTimeSpan;
      }
  }
  </code></pre>
  
  <p>Startup.cs:</p>
  
  <pre><code>public void ConfigureServices(IServiceCollection services)
  {
      ...
  
      services.AddDbContext&lt;Fit4YouDbContext&gt;(options =&gt;
              options.UseSqlServer(Configuration.GetConnectionString("MyConnectionString")));
  
      services.AddScoped&lt;IUnitOfWork, UnitOfWork&gt;();
      services.AddTransient&lt;IMailService, MailService&gt;();
  
      services.AddHostedService&lt;ConsumeScopedMailService&gt;();
      services.AddScoped&lt;IScopedMailService, ScopedMailService&gt;();
  
      ...
  }
  </code></pre>
  
  <p>MailService:</p>
  
  <pre><code>    public class MailService : IMailService
      {
          private readonly IUnitOfWork unitOfWork;
          public MailService(IUnitOfWork unitOfWork)
          {
              this.unitOfWork = unitOfWork;
          }
  
          public void SendNewsletterToSubscribedUsers()
          {
              // Some Code
          }
      }
  </code></pre>