Asp.net core 如何在API/backgroundworker中处理DbContext生存期
在过去的几天里,我一直在努力在我的后台工作人员中注入DbContext。一方面,我希望在Backgound worker中注入dbContext,但另一方面,我也希望在API中使用它 我的API中的注入似乎工作得很好,但由于我的工作者是一个单体,我不能遵循dbcontext的scoped的标准生存期,我必须将其作为瞬态添加 我已经尝试过创建一个工作单元,在这个工作单元中,我可以在我的worker中刷新上下文,从而有效地创建某种范围服务。每次工作人员再次执行循环时,我都会刷新上下文。这是可行的,应用程序按照我的要求运行,但我无法再进行正确的测试,因为我将自己在代码中创建一个新的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中刷新上下文,从而有效地创建某种范围服务。每次工作人员再次执行循环时,我都会刷新上下文。这是可行的,应
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;}