Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Dependency injection DbContext实例不随依赖项注入而更改_Dependency Injection_Entity Framework Core_Backgroundworker_Dbcontext - Fatal编程技术网

Dependency injection DbContext实例不随依赖项注入而更改

Dependency injection DbContext实例不随依赖项注入而更改,dependency-injection,entity-framework-core,backgroundworker,dbcontext,Dependency Injection,Entity Framework Core,Backgroundworker,Dbcontext,在我的应用程序中,我有一个API和一个worker,它们都需要使用我的数据库。我有一个存储库层,这两个层都可以访问。 我在应用程序中使用DI,并在存储库中注入dbContext 虽然我希望我的存储库在每个请求上都使用新的dbContext,但实例似乎总是相同的 因为我有一个后台工作程序,它是一个单例,所以我不能使用dbContext的默认作用域生存期。因此,我在worker和API中都添加了作为瞬态的dbContext。我已经在dbContext中添加了一个instanceId,它是在构造函数中

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

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

因为我有一个后台工作程序,它是一个单例,所以我不能使用dbContext的默认作用域生存期。因此,我在worker和API中都添加了作为瞬态的dbContext。我已经在dbContext中添加了一个instanceId,它是在构造函数中设置的

dbcontext的构造函数:

 public CatAPIDbContext()
    {
        InstanceId = Guid.NewGuid();
        Database.EnsureCreated();
    }
辅助服务器配置服务:

  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();
});
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));
}
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);
}
}
公共类GenericRepository:IGenericRepository其中T:class
{
公共CatAPIDbContext_dbContext{get;set;}
公共通用存储库(CatAPIDbContext dbContext)
{
_dbContext=dbContext;
}
公共T GetById(对象id)
{
返回_dbContext.Set().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:
GenericRepository,IFeedingProfileRepository
{
公共FeedingProfileRepository(CatAPIDbContext dbContext):
基本(dbContext)
{
}
公共FeedingProfile GetCurrentFeedingProfile()
{
var profile=\u dbContext.FeedingProfiles
.Include(x=>x.TimesToFeedOn)
.其中(x=>x.CurrentlyActive==true).FirstOrDefault();
if(profile==null)
{
返回null;
}
if(profile.TimesToFeedOn!=null)
{
profile.TimesToFeedOn=profile.TimesToFeedOn.OrderByDescending(x=>x.Time.ToList();
}
回报曲线;
}
}

当thw Worker调用FeedingProfileRepository.GetCurrentFeedingProfile()时,我会检查dbContext的instanceId,并且在应用程序的整个生命周期中它始终是相同的。因此,我从dbContext检索的数据已经过时,并且与数据库的当前状态不匹配,因为dbContext永远不会被释放。我做错了什么吗?

正如我在您的代码中看到的,您使dbContext成为瞬态的,这意味着每次注入或请求它们时都会创建一个新实例:

 services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Transient);
services.AddDbContext(ServiceLifetime.Transient);
如果希望所有请求都有一个实例,请将其设置为singleton,并尝试更改代码,如下所示:

services.AddDbContext<CatAPIDbContext>(ServiceLifetime.Singleton);
services.AddDbContext(ServiceLifetime.Singleton);
但是,如果您希望对应用程序的每个请求都有一个实例,请尝试使用作用域生存期:

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

如果我理解正确,dbContext应该是非常短暂的,因此我不想使用单例作用域。然而,问题是我想将dbContext用作作用域生存期,但我不能,因为我在我的worker中使用它,这是一个单例。我无法将作用域dbContext添加到我的singleton worker。最重要的是,我不希望短暂的生命周期(应该是最短的生命周期)在每次注入/请求时都保持不变,并且在我的应用程序的整个生命周期中都保持不变。您不能使用Singleton提供的作用域服务,请尽量避免这种情况,更多信息请阅读:我确实读过那篇文章,虽然它解释了我的问题,但它似乎并没有为“单例瞬态陷阱”提供解决方案。由于我别无选择,只能让我的工作者成为一个单例,并且我不能将我的dbContext添加为作用域,我觉得我别无选择,只能将其添加为瞬态,这再次导致了单例瞬态陷阱。我已经尝试在我的工作人员中保留我自己的范围,这很有效,但它显著降低了可测试性,所以我仍然在寻找更好的解决方案。