The following code
var merchant = await _dbContext.Merchants
.Include(m => m.Users)
.SingleAsync(m => m.MerchantId == id);
var userTasks = merchant.Users.Select(async u =>
{
var roles = await _userManager.GetRolesAsync(u);
return new MerchantUser
{
UserName = u.UserName,
Role = string.Join(",", roles)
};
}).ToList();
var users = await Task.WhenAll(userTasks);
return View(new MerchantViewModel
{
MerchantId = merchant.MerchantId,
MerchantName = merchant.Name,
MerchantUsers = users.ToList()
});
sometimes returns this error:
System.InvalidOperationException: A second operation started on this context before a previous operation completed.
However, this code does not. To my understanding, it's doing the same thing so I don't understand why it's failing.
var merchant = await _dbContext.Merchants
.Include(m => m.Users)
.SingleAsync(m => m.MerchantId == id);
var users = new List<MerchantUser>();
foreach (var user in merchant.Users)
{
var roles = await _userManager.GetRolesAsync(user);
users.Add(new MerchantUser
{
UserName = user.UserName,
Role = string.Join(",", roles)
});
}
return View(new MerchantViewModel
{
MerchantId = merchant.MerchantId,
MerchantName = merchant.Name,
MerchantUsers = users
});
var userTasks = merchant.Users.Select(async u => { … }).ToList();
var users = await Task.WhenAll(userTasks);
This will asynchronously start all those Select
tasks at the same time and then wait for them to complete. So this will run multiple things in parallel. Since you are querying the user manager inside, this will not work since the underlying connection does not support parallel queries.
In contrast, your foreach
loop will only run one query at a time, awaiting the GetRolesAsync
before the next iteration begins. So instead of working in parallel, the roles will be read sequentially for all users.
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.