I'm working on a Blazor server-side project where I need to fetch and join data from multiple tables using Entity Framework Core in the OnInitializedAsync
method. However, I'm encountering the following error:
InvalidOperationException: 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.
Here is my code below:
protected override async Task OnInitializedAsync()
{
PeopleTypes = await DbContext.PeopleTypes.Select(pts => new PeopleType
{
Id = pts.Id,
TypeName = pts.TypeName
}).ToListAsync() ?? new List<PeopleType>();
Peoples = await DbContext.People.Select(pl => new People
{
Id = pl.Id,
Name = pl.Name,
CompanyId = pl.CompanyId,
TypeId = pl.TypeId
}).ToListAsync() ?? new List<People>();
CompanyLists = await DbContext.CompanyList.Select(cl => new CompanyList
{
Id = cl.Id,
CompanyName = cl.CompanyName
}).ToListAsync() ?? new List<CompanyList>();
ClassDetails = await DbContext.ClassSessionsDetails
.Where(csd => csd.CsID == CSId)
.Where(csd => csd.CompanyId == selectedCompany)
.Select(csd => new ClassSessionDetails
{
Id = csd.Id,
CsID = csd.CsID
}).ToListAsync();
classMembersData = await DbContext.ClassSessionsDetails
.Join(DbContext.ClassSessionsMembers,
csd => csd.Id,
csm => csm.CSD_Id,
(csd, csm) => new { csd, csm })
.Join(DbContext.People,
combined => combined.csm.PeopleId,
people => people.Id,
(combined, people) => new { combined.csd, combined.csm, people })
.GroupJoin(DbContext.CompanyList,
combined => combined.people.CompanyId,
company => company.Id,
(combined, companies) => new { combined.csd, combined.csm, combined.people, company = companies.FirstOrDefault() })
.GroupJoin(DbContext.PeopleTypes,
combined => combined.people.TypeId,
peopleType => peopleType.Id,
(combined, peopleTypes) => new { combined.csd, combined.csm, combined.people, combined.company, peopleType = peopleTypes.FirstOrDefault() })
.Select(result => new ClassMembers
{
PeopleId = result.people.Id,
Name = result.people.Name,
CompanyId = result.company.Id,
CompanyName = result.company.CompanyName,
PeopleTypeId = result.peopleType.Id,
PeopleTypeName = result.peopleType.TypeName
}).ToListAsync();
await base.OnInitializedAsync();
}
Does anyone have suggestions on how to resolve this issue, or how I can improve my query to avoid concurrent operation conflicts? Thank you.
Merge multiple queries into one query to avoid multiple asynchronous calls to DbContext. This can avoid concurrent operations and improve performance.
Here is the sample
protected override async Task OnInitializedAsync()
{
var result = await (
from csd in DbContext.ClassSessionsDetails
join csm in DbContext.ClassSessionsMembers on csd.Id equals csm.CSD_Id
join p in DbContext.People on csm.PeopleId equals p.Id
join cl in DbContext.CompanyList on p.CompanyId equals cl.Id into companyGroup
from company in companyGroup.DefaultIfEmpty()
join pt in DbContext.PeopleTypes on p.TypeId equals pt.Id into peopleTypeGroup
from peopleType in peopleTypeGroup.DefaultIfEmpty()
where csd.CsID == CSId && csd.CompanyId == selectedCompany
select new ClassMembers
{
PeopleId = p.Id,
Name = p.Name,
CompanyId = company != null ? company.Id : (int?)null,
CompanyName = company != null ? company.CompanyName : null,
PeopleTypeId = peopleType != null ? peopleType.Id : (int?)null,
PeopleTypeName = peopleType != null ? peopleType.TypeName : null
}
).ToListAsync();
classMembersData = result;
await base.OnInitializedAsync();
}