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
}