Reputation: 1740
I'm using .Net Core Background Service to Connect to Kafka and save messages to SQL Server. My Project Structure looks like this:
In the Infrastructure Dependency, I have the following code to register Entity Framework
using IConfiguration configuration
passed from Worker's Program.cs
file i.e. services.AddInfrastructure(configuration)
;
namespace JS.Svf.BackgroundServices.Infrastructure
{
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
{
// Add all the dependencies required by Azure Functions.
// From Infrastructure
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
services.AddTransient<IApplicationDbContext>(provider => provider.GetRequiredService<ApplicationDbContext>());
services.AddTransient<IProductRepository, ProductRepository>();
services.AddTransient<ISupplierRepository, SupplierRepository>();
return services;
}
}
}
I'm getting the following error after running the Background Service:
Cannot consume scoped service 'ApplicationDbContext' from singleton 'Microsoft.Extensions.Hosting.IHostedService'
With reference, I came to know that we need to use IServiceScopeFactory
but I'm bit clueless about how to use it with the current structure. Please advice.
The repository uses the ApplicationDbContext
. How to use IServiceScopeFactory
here?
namespace JS.Svf.Functions.Infrastructure.Persistence
{
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
protected readonly ApplicationDbContext _context;
public Repository(ApplicationDbContext context)
{
_context = context;
}
public void Add(TEntity entity)
{
_context.Set<TEntity>().Add(entity);
_context.SaveChanges();
}
}
}
Upvotes: 2
Views: 5310
Reputation: 119076
In your singleton service, the IHostedService
, inject an IServiceScopeFactory
into it and use that to create a scope and get a new DbContext
from it. For example:
public class MyHostedService : IHostedService
{
private readonly IServiceScopeFactory _scopeFactory;
public MyHostedService(IServiceScopeFactory scopeFactory)
{
// Inject the scope factory
_scopeFactory = scopeFactory;
}
private async Task SomeMethodThatNeedsTheContext()
{
// Create a new scope (since DbContext is scoped by default)
using var scope = _scopeFactory.CreateScope();
// Get a Dbcontext from the scope
var context = scope.ServiceProvider
.GetRequiredService<ApplicationDbContext>();
// Run a query on your context
var quadrupeds = await context.Animals
.Where(a => a.Legs == 4)
.ToListAsync();
}
}
Upvotes: 5