如何将EF Core DbContext注入改为AddScoped解决已被跟踪报错
解决方案
直接修改AddDbContext方法的调用,显式指定生命周期参数即可,修改后的完整配置代码如下:
public override void Configure(IFunctionsHostBuilder builder) { // CCT database builder.Services.AddDbContext<sqldbCCTUKSATPPreProdContext>( options => { const string ConnString = "SQLConnectionStringCCT"; options.UseSqlServer(Configuration.GetConnectionString(ConnString)).UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll); }, contextLifetime: ServiceLifetime.Scoped, optionsLifetime: ServiceLifetime.Scoped); // CL database (Segimport DB) builder.Services.AddDbContext<sqldbCLSegImportUKSATPPreProdContext>( options => { const string CLConnString = "SQLConnectionStringCL"; options.UseSqlServer(Configuration.GetConnectionString(CLConnString)).UseQueryTrackingBehavior(QueryTrackingBehavior.TrackAll); options.EnableSensitiveDataLogging(); }, contextLifetime: ServiceLifetime.Scoped, optionsLifetime: ServiceLifetime.Scoped); }
补充说明
- EF Core 原生
AddDbContext方法默认的上下文生命周期就是Scoped,如果没有手动修改过生命周期参数,默认配置已经符合你的要求,显式指定参数是为了避免全局默认配置被修改导致的异常。 - 改完后每个请求Scope会创建独立的DbContext实例,天然避免不同操作下实体被重复跟踪的
already tracked报错。 - 不要在生命周期为Singleton的服务中直接注入Scoped类型的DbContext,会触发生命周期不匹配的异常,如果Singleton服务需要使用DbContext,需要手动创建Scope获取实例,示例代码如下:
public class SingletonService { private readonly IServiceProvider _serviceProvider; public SingletonService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void OperateDb() { // 手动创建Scope获取Scoped生命周期的DbContext using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService<sqldbCCTUKSATPPreProdContext>(); // 执行数据库操作 dbContext.SaveChanges(); } }
内容的提问来源于stack exchange,提问作者Jason_Hough
相关产品推荐
相关产品推荐

