У меня есть способ обновлять заявки пользователей в нашем приложении.
Я зарегистрирован как пользователь с правами администратора, который может редактировать других пользователей.
Я пытаюсь удалить существующие заявки одного пользователя и назначить новые.
При удалении претензий с использованием UserManger
в результате я получаю ConcurrencyFailure
. (Иногда это срабатывает, но в большинстве случаев возвращает ошибку.)
Код: "ConcurrencyFailure"
Описание: «Ошибка оптимистичного параллелизма, объект был изменен».
Метод:
public async Task<bool> AssignClaimsToUser(string id, List<string> newClaims)
{
bool success = false;
ApplicationUser user = await _userManager.FindByIdAsync(id);
List<Claim> userClaims = new List<Claim>();
// Remove existing claims
IList<Claim> existingClaims = await _userManager.GetClaimsAsync(user);
var removal = await _userManager.RemoveClaimsAsync(user, existingClaims); // This fail
if (removal.Succeeded)
{
success = true;
// Add new claims
foreach (string policy in newClaims)
{
userClaims.Add(new Claim(policy, string.Empty, ClaimValueTypes.String));
}
await _userManager.AddClaimsAsync(user, userClaims);
}
return success;
}
Почему это происходит и что делать, чтобы исправить эту проблему?
У меня эта проблема возникает только при снятии претензий. У меня его нет при вызове других методов на IdentityUser
.
ИЗМЕНИТЬ
Вывод отладки:
Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: ожидается, что операция с базой данных повлияет на 1 строку (строки), но фактически повлияла на 0 строк. Данные могли быть изменены или удалены после загрузки объектов. См. http://go.microsoft.com/fwlink/?LinkId=527962. для получения информации о понимании и обработке исключений оптимистичного параллелизма. на Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException (Int32 commandIndex, Int32, Int32 expectedRowsAffected rowsAffected) в Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagation (Int32 commandIndex, DbDataReader читателя) в Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.Consume (DbDataReader читателя ) в Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute (соединение IRelationalConnection) в Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute (IEnumerable
1 commandBatches, IRelationalConnection connection) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList
1 entriesToSave) в Microsoft.EntityChangeChangesChanges (Microsoft.EntityChangeChangeSave) EntityFrameworkCore.DbContext.SaveChanges (Boolean acceptAllChangesOnSuccess) Выведено исключение: 'Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException' в Microsoft.EntityFrameworkCore.dll Поток 0x6264 завершился с кодом 0 (0x0). Поток 0xaa0 завершился с кодом 0 (0x0). Поток 0x6a84 завершился с кодом 0 (0x0).ManageUsers_Update:
Почему это происходит?
Наиболее вероятная причина из-за конфликта параллелизма, когда несколько пользователей (потоков) попытались изменить одни и те же данные.
public async Task<ActionResult> ManageUsers_Update([DataSourceRequest] DataSourceRequest request, ManageUsersViewModel viewModel)
{
if (viewModel != null && ModelState.IsValid)
{
User objToUpdate = new User
{
Id = viewModel.ID,
FirstName = viewModel.FirstName,
Surname = viewModel.Surname
};
_userRepository.UpdateUser(objToUpdate);
if (viewModel.CustomerMenuId != null && viewModel.CustomerMenuId > 0)
{
int customerMenuId = Convert.ToInt32(viewModel.CustomerMenuId);
// Update user's claims
List<string> newClaims = _navigationRepository.GetPolicyNamesByCustomerMenuId(customerMenuId);
bool claimsUpdated = await _applicationUserService.AssignClaimsToUser(viewModel.AspNetUserId, newClaims);
// Assign user to menu if updating claims succeeded
if (claimsUpdated)
{
_navigationRepository.AssignCustomerMenuToUser(new CustomerMenuUser()
{CustomerMenuId = customerMenuId, AspNetUserId = viewModel.AspNetUserId});
}
}
ApplicationUser user = await _userManager.FindByIdAsync(viewModel.AspNetUserId);
user.IsEnabled = viewModel.IsEnabled;
await _userManager.UpdateAsync(user);
}
return Json(new[] { viewModel }.ToDataSourceResult(request, ModelState));
}