DBContext:没有调用Dispose()被处理掉了。不使用using语句。

3

我试图在我的dbcontext上调用一些查询。我已经将数据保存在数据库中,现在正在尝试从线程中再次提取数据进行进一步处理,但无法这样做。 dbcontext 被释放了。

我尝试将dbcontext的服务生存期从默认范围修改为 singleton 和 transient,并将调用dbcontext的类的生存期也更改为 transient。

服务添加 :

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<PearlIDPContext>(options => options.UseMySQL(Configuration.GetConnectionString("IDPDatabase")), optionsLifetime: ServiceLifetime.Transient);
    services.AddScoped<IScanDataRepository, ScanDataRepository>();
    services.AddScoped<IOperationsRepository, OperationHistoryRepository>();
    services.AddScoped<IExtractedDataRepository, ExtractedDataRepository>();
    services.AddScoped<IExtractedColorsRepository, ExtractedColorsRepository>();
    services.AddScoped<IRejectionsRepository, RejectionsRepository>();
    services.AddScoped<IStartProcess, StartProcess>();
}

数据库修改类:

public class ScanDataRepository : IScanDataRepository
{
    private readonly PearlIDPContext context;

    public ScanDataRepository(PearlIDPContext context)
    {
        this.context = context;
    }
    public async Task<ScanData> AddAsync(ScanData scan) [modified]
    {
        context.ScanData.Add(scan);
        await context.SaveChangesAsync();
        return scan;
    }
    public ScanData GetScanData(string pearlId)
    {
       return context.ScanData.FirstOrDefault(o => o.PearlId == pearlId);
    }
}

修改类的调用:

scanDataRepository.AddAsync(scanData);

try
{
    Logger.WriteToLogFile("Fetching Scan details from database for pearlID : " + pearlId, pearlId);

    scanData = scanDataRepository.GetScanData(pearlId); // this is line 39
    int id = scanData.ScanId;
    Logger.WriteToLogFile("Fetching Scan details from database successful for pearlID : " + pearlId + ". DB table id : " + id, pearlId);
}
catch (Exception ex)
{
    Logger.WriteToErrorFile("Error getting data from databse. Pearl ID : " + pearlId + ". Error : " + ex.ToString());
}

从数据库获取数据出错。Pearl ID : PI09889. 错误信息:系统.ObjectDisposedException: 无法访问已释放的对象。这种错误的常见原因是处置从依赖性注入解析的上下文,然后在应用程序的其他地方尝试使用相同的上下文实例。如果您对上下文调用Dispose() 或将上下文封装在using语句中,则可能会发生这种情况。如果正在使用依赖项注入,则应让依赖项注入容器处理上下文实例的处理。对象名称:'PearlIDPContext'。 在Microsoft.EntityFrameworkCore.DbContext.CheckDisposed() 中 在Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies() 中
在Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_StateManager() 中 在Microsoft.EntityFrameworkCore.Query.QueryContextDependencies.get_StateManager() 中 在Microsoft.EntityFrameworkCore.Query.QueryContext.get_StateManager() 中 在Microsoft.EntityFrameworkCore.Query.QueryContext.BeginTrackingQuery() 中 在Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results,QueryContext queryContext,IList`1 entityTrackingInfos,IList`1 entityAccessors)+MoveNext()中 在Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext()中 在System.Linq.Enumerable.TryGetFirst [TSource](IEnumerable`1 source,Boolean & found)中 在System.Linq.Enumerable.First [TSource](IEnumerable`1 source)中 在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.b__0(QueryContext qc)中 在Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute [TResult](Expression query)中 在Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute [TResult](Expression expression)中 在System.Linq.Queryable.FirstOrDefault [TSource](IQueryable`1 source,Expression`1 predicate)中 在MyndIT.Models.ScanDataRepository.GetScanData(String pearlId)中的D:\Projects\Github\PearlIDP\MyndIT\Models\ScanDataRepository.cs:line 33 在MyndIT.StartProcess.ProcessStart(String pearlId)中的D:\Projects\Github\PearlIDP\MyndIT\StartProcess.cs:line 39

1
不要使用Singleton来处理数据库上下文,它们是轻量级、短暂的东西。应该使用适当的短生命周期进行注入,并且不要试图以任何方式保留它们。 - Caius Jard
这是我尝试过的其中一件事。通常我将其保持为Scoped并会出现上述错误。 - Exorcist
1
在Dispose上设置一个断点,你就会看到是谁在处理它。 - Manuel Amstutz
我没有显式地调用Dispose方法。您能指导我在哪里检查dispose方法吗? - Exorcist
2个回答

2

您需要将DbContext保持为瞬态。我以前遇到过这个问题。问题在于方法完成并且在线程完成之前处理了上下文的释放。如果您正在使用线程防止UI锁定,则应使用await关键字(实际上您无论如何都应该使用await)。


已将其设置为瞬态。所有调用dbcontext的模型都是作用域的。services.AddDbContext<PearlIDPContext>(options => options.UseMySQL(Configuration.GetConnectionString("IDPDatabase")), optionsLifetime: ServiceLifetime.Transient); services.AddScoped<IScanDataRepository, ScanDataRepository>(); services.AddScoped<IOperationsRepository, OperationHistoryRepository>(); services.AddScoped<IExtractedDataRepository, ExtractedDataRepository>(); - Exorcist

0
请确保在找到此行的代码中:
scanDataRepository.Add(scanData);

是否已正确等待。如果此代码在返回任务的方法内执行,并且该任务未被正确等待,则数据库可能会被释放,因为调用方已经完成,尽管您的数据库操作仍处于挂起状态。


好的,明白了。 - Exorcist
已将所有的add方法更改为使用async和await。但是我仍然收到错误提示: - Exorcist
{ context.ScanData.Add(scan); await context.SaveChangesAsync(); return scan; }``` 已经使用了await关键字来等待所有添加方法。问题仍然存在。已经更新了问题并使用了await方法。 - Exorcist

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接