I'm trying to save all the KPI values that have been passed from View, but I ran into a problem, where I used foreach loop and this operation took way too long to process, so I loooked for solution and found Parallel.ForEach, but it throws me this error:
An attempt was made to use the context while it is being configured. A DbContext instance cannot be used inside 'OnConfiguring' since it is still being configured at this point. This can happen if a second operation is started on this context before a previous operation completed.
Code:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create([Bind("Date,Name,Value,ID,CriteriaID,Employee")] List<KPI> KPI, List<string> employeeGIDs)
{
if (KPI.Count == 0)
return Create();
int managerID = HttpContext.Session.GetInt32("ID").Value;
var criterias = _context.Criterias.AsEnumerable().Where(x => KPI.Any(k => k.CriteriaID == x.ID));
var users = _context.Users.AsEnumerable().Where(x => employeeGIDs.Contains(x.GID));
var managerKPIs = _context.KPIs.AsEnumerable().Where(x => x.ManagersId == managerID);
List<KPI> kpisToAdd = new List<KPI>(KPI);
if (ModelState.IsValid)
{
ParallelLoopResult parallelLoopResult = Parallel.ForEach(kpisToAdd, kpi =>
{
kpi.ManagersId = managerID;
kpi.Criteria = criterias.FirstOrDefault(x => x.ID == kpi.CriteriaID);
var user = users.FirstOrDefault(x => employeeGIDs.Contains(x.GID));
if (kpi.Criteria.IsIndividual)
{
kpi.EmployeeUserCode = user.UserCode;
kpi.EmployeeFullName = user.FullName;
}
});
if (parallelLoopResult.IsCompleted)
{
var criteriasToAdd = kpisToAdd
.Where(x => !managerKPIs
.Any(m =>
m.Date.Month.Equals(x.Date.Date.Month) &&
m.EmployeeUserCode.Equals(x.EmployeeUserCode) &&
m.Criteria.Name.Equals(x.Criteria.Name)));
_context.AddRange(criteriasToAdd);
await _context.SaveChangesAsync();
}
}
return Create();
}
I tried wrapping it into Task, but it doesn't work. Are there any alternatives?