Trying to get Dropdown list to loaded in parallel but Context thread issue is occurring with my repo patterns

Viewed 18

currently, this method will load my DropDownList data :

private async Task LoadStandAloneListData()
{

    try
    {
        SalesRepList = await UnitOfWork.SalesReps.GetDropDownListNoTracking() as IReadOnlyList<DropDownList>; ;
        ProposalStatusList = await UnitOfWork.ProposalStatus.GetDropDownListNoTracking();
        SourceList = await UnitOfWork.Sources.GetDropDownListNoTracking();
        YearOptionsList = await UnitOfWork.Year.GetDropDownListNoTracking();
        OutForBidList = await UnitOfWork.CompBid.GetDropDownListNoTracking();
        InfoSecAwareList = await UnitOfWork.InfoSecAware.GetDropDownListNoTracking();
        TimeDriverList = await UnitOfWork.TimeDriver.GetDropDownListNoTracking();
        NeedsDriverList = await UnitOfWork.NeedsDriver.GetDropDownListNoTracking();

    }
    catch (Exception exception)
    {
        _errorMessage = exception.Message;
        _Status = Status.Error;
        return;
    }
}

The Form (edit/create) that this supports takes a bit to load so I was trying to improve performance by loading each on a different thread.

I add the following method to my UnitOfWork pattern

    public async Task<DropDownDataList> LoadProposalsInterfaceDropdownList()
{
    
   var data = new DropDownDataList();

    var SalesRepListTasks = SalesReps.GetDropDownListNoTracking();
    var ProposalStatusListTasks = ProposalStatus.GetDropDownListNoTracking();
    var SourceListTasks = Sources.GetDropDownListNoTracking();
    var YearOptionsListTasks = Year.GetDropDownListNoTracking();
    var OutForBidListTasks = CompBid.GetDropDownListNoTracking();
    var InfoSecAwareListTasks = InfoSecAware.GetDropDownListNoTracking();
    var TimeDriverListTasks = TimeDriver.GetDropDownListNoTracking();
    var NeedsDriverListTasks = NeedsDriver.GetDropDownListNoTracking();
    await Task.WhenAll(
       SalesRepListTasks,
       ProposalStatusListTasks,
       SourceListTasks,
       YearOptionsListTasks,
       OutForBidListTasks,
       InfoSecAwareListTasks,
       TimeDriverListTasks,
       NeedsDriverListTasks);


    data.SalesRepList = await SalesRepListTasks as IReadOnlyList<DropDownList>;
    data.ProposalStatusList = await ProposalStatusListTasks;
    data.SourceList = await SourceListTasks;
    data.YearOptionsList = await YearOptionsListTasks;
    data.OutForBidList = await OutForBidListTasks;
    data.InfoSecAwareList = await InfoSecAwareListTasks;
    data.TimeDriverList = await TimeDriverListTasks;
    data.NeedsDriverList = await NeedsDriverListTasks;

    return data;
}

When I test the new method I get the following error :

A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext. For more information on how to avoid threading issues with DbContext,

I've done some searching only and they mentioned defining my context as transient I check my program.cs files

builder.Services.AddDbContext<DbContext>(options => { options.UseSqlServer(connectionString); }, ServiceLifetime.Transient);

Is there something I'm missing? or is my unit of work /repo pattern not compatible with this?

As a reference here a slimmed-down copy of my unit of work :

public class UnitOfWork : IUnitOfWork
{
    private readonly DbContext _context;
    private readonly ILogger<UnitOfWork> _logger;
    //redacted
    public ISalesRepRepository SalesReps { get;  set; }
    public IProposalStatusRepository ProposalStatus { get;  set; }
    public ISourceRepository Sources { get;  set; }
    public IYearRepository Year { get;  set; }
    public ICompBidsRepository CompBid { get;  set; }
    public IInfoSecAwareRepository InfoSecAware { get;  set; }
    public ITimeDriverRepository TimeDriver { get;  set; }
    public INeedsDriverRepository NeedsDriver { get;  set; }
    //redacted
      public UnitOfWork(DbContext context, ILogger<UnitOfWork> logger)
    {
        _context = context;
        _logger = logger;
        //redacted
        SalesReps = new SalesRepRepository(_context);
         Sources = new SourceRepository(_context);
        ProposalStatus = new ProposalStatusRepository(_context);
        Year = new YearRepository(_context);
        CompBid = new CompBidsRepository(_context);
        InfoSecAware = new InfoSecAwareRepository(_context);
        NeedsDriver = new NeedsDriverRepository(_context);
        TimeDriver = new TimeDriverRepository(_context);
        //redacted
    }
    //redacted
    public async Task<DropDownDataList> LoadProposalsInterfaceDropdownList()
    {
        
       var data = new DropDownDataList();


        var SalesRepListTasks = SalesReps.GetDropDownListNoTracking();
        var ProposalStatusListTasks = ProposalStatus.GetDropDownListNoTracking();
        var SourceListTasks = Sources.GetDropDownListNoTracking();
        var YearOptionsListTasks = Year.GetDropDownListNoTracking();
        var OutForBidListTasks = CompBid.GetDropDownListNoTracking();
        var InfoSecAwareListTasks = InfoSecAware.GetDropDownListNoTracking();
        var TimeDriverListTasks = TimeDriver.GetDropDownListNoTracking();
        var NeedsDriverListTasks = NeedsDriver.GetDropDownListNoTracking();
        await Task.WhenAll(
           SalesRepListTasks,
           ProposalStatusListTasks,
           SourceListTasks,
           YearOptionsListTasks,
           OutForBidListTasks,
           InfoSecAwareListTasks,
           TimeDriverListTasks,
           NeedsDriverListTasks);


        data.SalesRepList = await SalesRepListTasks as IReadOnlyList<DropDownList>;
        data.ProposalStatusList = await ProposalStatusListTasks;
        data.SourceList = await SourceListTasks;
        data.YearOptionsList = await YearOptionsListTasks;
        data.OutForBidList = await OutForBidListTasks;
        data.InfoSecAwareList = await InfoSecAwareListTasks;
        data.TimeDriverList = await TimeDriverListTasks;
        data.NeedsDriverList = await NeedsDriverListTasks;

        return data;
    }
    //redacted
}
0 Answers
Related