How to inject a DbContext instance into an IHostedService
Problem Statement
Few days back, I was working on a class which implemented IHostedService. I was working on asp.net core project. I tried to use DbContext class using constructor. But, it shows the following error -
Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions' from singleton 'Microsoft.Extensions.Hosting.IHostedService'.
I tried it several way but I failed.
Solution
Step 1: I have injected IserviceScopeFactory and solve the problem as like below.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Ordering.API.Db;
using Plain.RabbitMQ;
using Shared.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Ordering.API
{
public class CatalogResponseListener : IHostedService
{
private ISubscriber _subscriber;
private readonly IServiceScopeFactory _scopeFactory;
public CatalogResponseListener(ISubscriber subscripber, IServiceScopeFactory scopeFactory)
{
this._subscriber = subscripber;
this._scopeFactory = scopeFactory;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_subscriber.Subscribe(Subscribe);
return Task.CompletedTask;
}
private bool Subscribe(string message, IDictionary<string, object> header)
{
var response = JsonConvert.DeserializeObject<CatalogResponse>(message);
if(!response.IsSuccess)
{
using (var scope = _scopeFactory.CreateScope())
{
var _orderingContext = scope.ServiceProvider.GetRequiredService<OrderingContext>();
// Remove ordering item
var orderItem = _orderingContext.OrderItems.Where(o => o.ProductId == response.CatalogId).FirstOrDefault();
_orderingContext.OrderItems.Remove(orderItem);
_orderingContext.SaveChanges();
}
}
return true;
}
public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
}