简体   繁体   中英

Common DB Access repository for ASP.NET Core Web App and Worker Service - managing context

I have an app with a common database requirement for an ASP.Net Core web app and an ASP.Net Core Worker service background task. I have a standard Repository pattern based approach with a class for each entity (standard CRUD operations).

My question concerns the best approach to manage the Db context injection into the Repository class for both apps. This is easy for the ASP.Net Core web app: Constructor based DI each time a Db context is required. However, the worker service requires obtaining a fresh Db context for every ExecuteAsync iteration, and passing it to each repository class by some means. This works, but is a bit messy:

code

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var scope = _serviceScopeFactory.CreateScope();

            var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
            
            ...
        }
    }

code

I'm interested in a single Db data access point design pattern that will manage both apps while also getting thread-safe Db contexts when required.

Any help greatly appreciated

I have come up with a workable Repository Pattern per entity implementation that works for both the ASP.NET core web app and Worker Service. Here is the code to do this:

public interface IApplianceRepository
{
    Task UpdateApplianceDetailsAsync(Appliance appliance);
    Task CreateApplianceAsync(Appliance appliance);
    …
}
public class SqlApplianceRepository : IApplianceRepository
{ 
    protected IDbContext _db;
    public SqlApplianceRepository() {}

    public SqlApplianceRepository(IDbContext db)
    {
        _db = db;
    }
    public virtual async Task CreateApplianceDetailsAsync(Appliance appliance)
    {
        …
    }
    public virtual async Task UpdateApplianceDetailsAsync(Appliance appliance)
    {
        …
    }
    …
}   
public class SqlApplianceRepositoryWorkerService : SqlApplianceRepository
{
    public override async Task CreateApplianceAsync(Appliance appliance)
    {
        _db = DbContextFactory.GetCurrentDbContext();
        await base.CreateApplianceAsync(appliance);
    }
    public override async Task UpdateApplianceDetailsAsync(Appliance appliance)
    {
        _db = DbContextFactory.GetCurrentDbContext();
        await base.UpdateApplianceDetailsAsync(appliance);
    }
    …
}

Both SqlApplianceRepository and SqlApplianceRepositoryWorkerService are configured as transient services and injected where required in their respective apps. DbContextFactory.GetCurrentDbContext() gets a Db context created for every Worker Service call to ExecuteAsync().

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM