在我的应用程序中,我有一个API和一个worker,它们都需要使用我的数据库。我有一个存储库层,这两个层都可以访问。我在应用程序中使用DI,然后将dbContext注入存储库中。
虽然我希望我的存储库在每个请求上都使用一个新的dbContext,但是实例似乎总是相同的。
由于我有一个后台工作程序,它是一个单例,因此我无法使用dbContext的默认作用域生存期。因此,我在我的worker和API中都将dbContext添加为瞬态。我已将一个instanceId添加到我的dbContext中,该值在构造函数中设置。
dbcontext的构造方法:
public CatAPIDbContext()
{
InstanceId = Guid.NewGuid();
Database.EnsureCreated();
}
Worker configureservices:
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>();
});
API ConfigureServices:
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<>));
}
GenericRepo示例:
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);
}
}
我使用的回购,但未获得最新状态示例:
public class FeedingProfileRepository :
GenericRepository<FeedingProfile>, IFeedingProfileRepository
{
public FeedingProfileRepository(CatAPIDbContext dbContext) :
base(dbContext)
{
}
public FeedingProfile GetCurrentFeedingProfile()
{
var profile = _dbContext.FeedingProfiles
.Include(x => x.TimesToFeedOn)
.Where(x => x.CurrentlyActive == true).FirstOrDefault();
if (profile == null)
{
return null;
}
if (profile.TimesToFeedOn != null)
{
profile.TimesToFeedOn = profile.TimesToFeedOn.OrderByDescending(x => x.Time).ToList();
}
return profile;
}
}
当管理员调用FeedingProfileRepository.GetCurrentFeedingProfile()时,我检查dbContext的instanceId,在我的应用程序的整个生命周期中,它始终是相同的。结果,我从dbContext检索的数据已过时,并且与dbContext的当前状态不匹配,因为dbContext从未被丢弃。我做错了吗?
正如我在您的代码中所看到的,您已经使dbContext Transient成为临时对象,这意味着它在每次注入或请求它们时都会创建一个新实例:
services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Transient);
如果您希望所有请求都具有一个实例,请使其单例尝试更改代码,如下所示:
services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Singleton);
但是,如果您希望对应用程序的每个请求都具有一个实例,请尝试使用作用域生存期:
services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Scoped);