Asp.net core 如何在API/backgroundworker中处理DbContext生存期

Asp.net core 如何在API/backgroundworker中处理DbContext生存期,asp.net-core,dependency-injection,.net-core,backgroundworker,dbcontext,Asp.net Core,Dependency Injection,.net Core,Backgroundworker,Dbcontext,在过去的几天里,我一直在努力在我的后台工作人员中注入DbContext。一方面,我希望在Backgound worker中注入dbContext,但另一方面,我也希望在API中使用它 我的API中的注入似乎工作得很好,但由于我的工作者是一个单体,我不能遵循dbcontext的scoped的标准生存期,我必须将其作为瞬态添加 我已经尝试过创建一个工作单元,在这个工作单元中,我可以在我的worker中刷新上下文,从而有效地创建某种范围服务。每次工作人员再次执行循环时,我都会刷新上下文。这是可行的,应

在过去的几天里,我一直在努力在我的后台工作人员中注入DbContext。一方面,我希望在Backgound worker中注入dbContext,但另一方面,我也希望在API中使用它

我的API中的注入似乎工作得很好,但由于我的工作者是一个单体,我不能遵循dbcontext的scoped的标准生存期,我必须将其作为瞬态添加

我已经尝试过创建一个工作单元,在这个工作单元中,我可以在我的worker中刷新上下文,从而有效地创建某种范围服务。每次工作人员再次执行循环时,我都会刷新上下文。这是可行的,应用程序按照我的要求运行,但我无法再进行正确的测试,因为我将自己在代码中创建一个新的DbContext。我觉得一定有更好的方法来处理这件事

我的项目结构如下所示:

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    public CatAPIDbContext _dbContext { get; set; }
    public GenericRepository(CatAPIDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public T GetById(object id)
    {
        return _dbContext.Set<T>().Find(id);
    }
}
API=>包含我用于post请求的控制器+模型。 API项目需要使用我的数据库来获取和发布数据。它为此使用存储库

核心(类库)=>包含一些核心模型

域(类库)=>包含我的域模型+存储库。 所有的数据库工作都在这里完成

Worker=>包含一些逻辑。 工人需要使用我的数据库来获取和发布数据。它为此使用存储库

服务(类库)=>包含某些逻辑的某些服务。 工作人员使用我的存储库访问数据库

Tests=>所有代码的测试。 我希望在这里也能进行集成测试

我目前在API和worker中注入了所有存储库和服务:

辅助服务器配置服务:

  public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Transient);
                services.AddTransient(typeof(IFeedingProfileRepository), typeof(FeedingProfileRepository));
                services.AddTransient(typeof(IFeedingTimesRepository), typeof(FeedingTimesRepository));
                services.AddTransient(typeof(IFeedHistoryRepository), typeof(FeedHistoryRepository));
                services.AddTransient(typeof(IMotorController), typeof(MotorController));
                services.AddTransient(typeof(IFoodDispenser), typeof(FoodDispenser));
                services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
                services.AddTransient(typeof(IFeedingTimeChecker), typeof(FeedingTimeChecker));
                services.AddHostedService<Worker>();
            });
公共静态IHostBuilder CreateHostBuilder(字符串[]args)=>
Host.CreateDefaultBuilder(args)
.ConfigureServices((主机上下文,服务)=>
{
services.AddDbContext(ServiceLifetime.Transient);
AddTransient(typeof(IFeedingProfileRepository)、typeof(FeedingProfileRepository));
服务。添加瞬态(类型of(IFeedingTimesRepository),类型of(FeedingTimesRepository));
AddTransient(typeof(IFeedHistoryRepository)、typeof(FeedHistoryRepository));
服务。AddTransient(类型为(IMotorController),类型为(MotorController));
AddTransient(typeof(IFoodDispenser),typeof(FoodDispenser));
服务.AddTransient(typeof(IGenericRepository)、typeof(genericpository));
服务.AddTransient(类型of(IFeedingTimeChecker),类型of(FeedingTimeChecker));
services.AddHostedService();
});
(编辑)工人代码:

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;
    public IFeedingTimeChecker _feedingTimeChecker { get; }
    public Worker(ILogger<Worker> logger, IFeedingTimeChecker feedingTimeChecker)
    {
        _logger = logger;
        _feedingTimeChecker = feedingTimeChecker;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                _feedingTimeChecker.ResetFeedingTimesGivenIfNeeded();
                _feedingTimeChecker.FeedIfNeeded();
            }
            catch(Exception ex)
            {
                _logger.LogError(ex.ToString());
            }
            await Task.Delay(10000, stoppingToken);
        }
    }
}
public class Worker:BackgroundService
{
专用只读ILogger\u记录器;
公共IFeedingTimeChecker\u feedingTimeChecker{get;}
公共工作者(ILogger记录器,IFeedingTimeChecker feedingTimeChecker)
{
_记录器=记录器;
_feedingTimeChecker=feedingTimeChecker;
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
同时(!stoppingToken.IsCancellationRequested)
{
尝试
{
_logger.LogInformation(“在:{time}运行的工作进程”,DateTimeOffset.Now);
_feedingTimeChecker.ResetFeedingTimesGiveNifRequired();
_feedingTimeChecker.FeedIfNeeded();
}
捕获(例外情况除外)
{
_logger.LogError(例如ToString());
}
等待任务。延迟(10000,停止待命);
}
}
}
(编辑)FeedingTimeChecker(由工作人员调用)

private FeedingProfile\u currentProfile{get;set;}
公共日期时间lastResetDataFeedingTimes;
公共DateTime lastProfileRefresh;
专用只读ILogger\u记录器;
私有IFeedingProfileRepository_feedingProfileRepository{get;set;}
private IFeedingTimesRepository_feedingTimesRepository{get;set;}
私有IFoodDispenser\u foodDispenser{get;}
公共FeedingTimeChecker(IFeedingProfileRepository feedingProfileRepository,IFeedingTimesRepository feedingTimesRepository,IFoodDispenser foodDispenser,ILogger logger)
{
lastResetDataFeedingTimes=DateTime.MinValue.Date;
lastProfileRefresh=DateTime.MinValue.Date;
_foodDispenser=foodDispenser;
_记录器=记录器;
_feedingTimesRepository=feedingTimesRepository;
_feedingProfileRepository=feedingProfileRepository;
}        
public void UpdateCurrentProfile()
{
if(Time.GetDateTimeNow-TimeSpan.FromSeconds(5)>lastProfileRefresh)
{
_logger.LogInformation(“刷新当前配置文件”);
_currentProfile=_feedingProfileRepository.GetCurrentFeedingProfile();
lastProfileRefresh=Time.GetDateTimeNow;
}
}
API配置服务:

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvcCore().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
        services.AddDbContext<CatAPIDbContext>();
        services.AddTransient(typeof(IFeedingProfileRepository), typeof(FeedingProfileRepository));
        services.AddTransient(typeof(IFeedingTimesRepository), typeof(FeedingTimesRepository));
        services.AddTransient(typeof(IFeedHistoryRepository), typeof(FeedHistoryRepository));
        services.AddTransient(typeof(IMotorController), typeof(MotorController));
        services.AddTransient(typeof(IFoodDispenser), typeof(FoodDispenser));
        services.AddTransient(typeof(IGenericRepository<>), typeof(GenericRepository<>));
    }
public void配置服务(IServiceCollection服务)
{
services.AddMvcCore().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
services.AddDbContext();
AddTransient(typeof(IFeedingProfileRepository)、typeof(FeedingProfileRepository));
服务。添加瞬态(类型of(IFeedingTimesRepository),类型of(FeedingTimesRepository));
AddTransient(typeof(IFeedHistoryRepository)、typeof(FeedHistoryRepository));
服务。AddTransient(类型为(IMotorController),类型为(MotorController));
AddTransient(typeof(IFoodDispenser),typeof(FoodDispenser));
服务.AddTransient(typeof(IGenericRepository)、typeof(genericpository));
}
在我的存储库中,我使用dbContext,如下所示:

public class GenericRepository<T> : IGenericRepository<T> where T : class
{
    public CatAPIDbContext _dbContext { get; set; }
    public GenericRepository(CatAPIDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public T GetById(object id)
    {
        return _dbContext.Set<T>().Find(id);
    }
}
公共类GenericRepository:IGenericRepository其中T:class
{
公共CatAPIDbContext_dbContext{get;set;}