DbContext实例不会因依赖项注入而改变

时间:2019-10-29 17:58:03

标签: dependency-injection entity-framework-core backgroundworker dbcontext

在我的应用程序中,我有一个API和一个worker,它们都需要使用我的数据库。我有一个存储库层,这两个层都可以访问。 我在应用程序中使用DI,然后将dbContext注入存储库中。

虽然我希望我的存储库在每个请求上都使用一个新的dbContext,但实例似乎总是相同的。

由于我有一个后台工作程序,它是一个单例,因此我无法使用dbContext的默认作用域生存期。因此,我在我的worker和AP​​I中都将dbContext添加为瞬态。我已经在我的dbContext中添加了一个instanceId,它是在构造函数中设置的。

dbcontext的构造函数:

 public CatAPIDbContext()
    {
        InstanceId = Guid.NewGuid();
        Database.EnsureCreated();
    }

工作者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从未被丢弃。我在做错什么吗?

1 个答案:

答案 0 :(得分:0)

正如我在您的代码中看到的那样,您已经使dbContext Transient成为临时对象,这意味着每次注入或请求dbContext时都会创建一个新实例:

 services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Transient);

如果您希望所有请求都具有一个实例,请使其单例尝试更改代码,如下所示:

services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Singleton);

但是,如果您希望对应用程序的每个请求都具有一个实例,请尝试使用作用域生存期:

 services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Scoped);