简体   繁体   中英

DBContext : Getting disposed without calling Dispose(). Not using a using statement

I am trying to call some queries on my dbcontext . I have saved the data in the DB, and am now trying to extract the data again in a thread to do further processing, but unable to do so. The dbcontext comes up as disposed.

I have tried modifying the service lifetime of the dbcontext to singleton and transient from default scoped as well as changed the lifetime of classed calling the dbcontext to transient.

Services Addition:

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>();
}

Db modification class:

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);
    }
}

calls to modification class:

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());
}

Error getting data from database. Pearl ID: PI09889. Error: System.ObjectDisposedException: Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application. This may occur if you are calling Dispose() on the context, or wrapping the context in a using statement. If you are using dependency injection, you should let the dependency injection container take care of disposing context instances. Object name: 'PearlIDPContext'. at Microsoft.EntityFrameworkCore.DbContext.CheckDisposed() at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
at Microsoft.EntityFrameworkCore.DbContext.Microsoft.EntityFrameworkCore.Internal.IDbContextDependencies.get_StateManager() at Microsoft.EntityFrameworkCore.Query.QueryContextDependencies.get_StateManager() at Microsoft.EntityFrameworkCore.Query.QueryContext.get_StateManager() at Microsoft.EntityFrameworkCore.Query.QueryContext.BeginTrackingQuery() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable`1 results, QueryContext queryContext, IList`1 entityTrackingInfos, IList`1 entityAccessors)+MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor`1.EnumeratorExceptionInterceptor.MoveNext() at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Boolean& found) at System.Linq.Enumerable.First[TSource](IEnumerable`1 source) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass15_1`1.b__0(QueryCo ntext qc) at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query) at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression) at System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source, Expression`1 predicate) at MyndIT.Models.ScanDataRepository.GetScanData(String pearlId) in D:\Projects\Github\PearlIDP\MyndIT\Models\ScanDataRepository.cs:line 33 at MyndIT.StartProcess.ProcessStart(String pearlId) in D:\Projects\Github\PearlIDP\MyndIT\StartProcess.cs:line 39

You need to keep your DbContext as transient. I've had this problem many times before. What's happening is that the method is finishing and disposing of your context Before your thread is finished. If you are using a thread to stop UI from locking then you should use the await keyword (actually you should use await anyway).

Please make sure that the code where this line is found:

scanDataRepository.Add(scanData);

Is awaited properly. If this code is executed inside a method that returns a Task, and that task is not awaited properly, then the database could end up being disposed, because the caller has already finished, even though your database operations are still pending.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM