(已解决)如何强制捕获异常? (或检索异常变量)
(SOLVED) How do I force the catch exception? (or retrieve exception variable)
如何强制我的 else 语句转到 catch 异常?我得到了这个代码:
try
{
user.UserName = editedUser.Username;
user.Email = editedUser.Email;
user.RowVersion = editedUser.RowVersion;
var result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
return RedirectToAction("ListOfUsers");
}
else
{
Somehow go to Catch(DbUpdateConcurrencyException ex) // <---------- How?
}
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (ApplicationUser)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, $"User{editedUser.ID} was deleted before you applied the changes.");
}
else
{
var databaseValues = (ApplicationUser)databaseEntry.ToObject();
if (databaseValues.UserName != clientValues.UserName)
{
ModelState.AddModelError("Username", $"Current username in Database: {databaseValues.UserName}");
}
if (databaseValues.Email != clientValues.Email)
{
ModelState.AddModelError("Email", $"Current email in Database: {databaseValues.Email}");
}
ModelState.AddModelError(string.Empty, "The user you were trying to edit was modified by someone else. Editing operation was canceled and the current values in the database are now shown below. If you still want to edit this user, click Save again, otherwise click Undo");
user.RowVersion = databaseValues.RowVersion;
ModelState.Remove("RowVersion");
}
}
我需要使用 DbUpdateConcurrencyException ex 变量来获取我的数据库条目值。
如果可以在 else 语句中获取这些数据库条目值,我该怎么做?
编辑 - 解决方案:
我发现我们应该避免这种情况并处理代码中的错误,而不是使用 Try/catch,即 if-else。在 else 语句中,我找到了 Identity 使用的异常,并进行了处理。并获取数据库值,我使用了:
var dbUser = await userManager.Users.AsNoTracking().SingleOrDefaultAsync(x => x.Id == user.Id);
通过这样做,我可以比较 'dbUser' 和 'user' 的属性。
我明白你在追求什么,但是方法完全错误。
DbUpdateConcurrencyException
是 EF Core 特定的异常,而身份是抽象框架,因此设计的这个异常永远不会流动,因此永远不会命中 catch
。
根据设计,错误通过 IdentityResult.Errors
提供,并发问题默认提供 IdenitityError.Code
等于“ConcurrencyFailure”,可以在 EF Core store implementation 中看到:
try
{
await SaveChanges(cancellationToken);
}
catch (DbUpdateConcurrencyException)
{
return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure());
}
所以你需要重构代码。删除整个 catch
块,并在 else
子句中检查并发错误,如果是,则使用 UserManager.FindByIdAsync
获取当前(数据库)数据并执行您的逻辑。
像这样:
else
{
var concurrencyError = result.Errors.FirstOrDefault(error =>
error.Code == nameof(IdentityErrorDescriber.ConcurrencyFailure));
if (concurrencyError != null)
{
var dbUser = await userManager.FindByIdAsync(user.Id);
// Check for null(deleted) or modified properties here
}
}
如何强制我的 else 语句转到 catch 异常?我得到了这个代码:
try
{
user.UserName = editedUser.Username;
user.Email = editedUser.Email;
user.RowVersion = editedUser.RowVersion;
var result = await userManager.UpdateAsync(user);
if (result.Succeeded)
{
return RedirectToAction("ListOfUsers");
}
else
{
Somehow go to Catch(DbUpdateConcurrencyException ex) // <---------- How?
}
}
catch (DbUpdateConcurrencyException ex)
{
var exceptionEntry = ex.Entries.Single();
var clientValues = (ApplicationUser)exceptionEntry.Entity;
var databaseEntry = exceptionEntry.GetDatabaseValues();
if (databaseEntry == null)
{
ModelState.AddModelError(string.Empty, $"User{editedUser.ID} was deleted before you applied the changes.");
}
else
{
var databaseValues = (ApplicationUser)databaseEntry.ToObject();
if (databaseValues.UserName != clientValues.UserName)
{
ModelState.AddModelError("Username", $"Current username in Database: {databaseValues.UserName}");
}
if (databaseValues.Email != clientValues.Email)
{
ModelState.AddModelError("Email", $"Current email in Database: {databaseValues.Email}");
}
ModelState.AddModelError(string.Empty, "The user you were trying to edit was modified by someone else. Editing operation was canceled and the current values in the database are now shown below. If you still want to edit this user, click Save again, otherwise click Undo");
user.RowVersion = databaseValues.RowVersion;
ModelState.Remove("RowVersion");
}
}
我需要使用 DbUpdateConcurrencyException ex 变量来获取我的数据库条目值。
如果可以在 else 语句中获取这些数据库条目值,我该怎么做?
编辑 - 解决方案: 我发现我们应该避免这种情况并处理代码中的错误,而不是使用 Try/catch,即 if-else。在 else 语句中,我找到了 Identity 使用的异常,并进行了处理。并获取数据库值,我使用了:
var dbUser = await userManager.Users.AsNoTracking().SingleOrDefaultAsync(x => x.Id == user.Id);
通过这样做,我可以比较 'dbUser' 和 'user' 的属性。
我明白你在追求什么,但是方法完全错误。
DbUpdateConcurrencyException
是 EF Core 特定的异常,而身份是抽象框架,因此设计的这个异常永远不会流动,因此永远不会命中 catch
。
根据设计,错误通过 IdentityResult.Errors
提供,并发问题默认提供 IdenitityError.Code
等于“ConcurrencyFailure”,可以在 EF Core store implementation 中看到:
try { await SaveChanges(cancellationToken); } catch (DbUpdateConcurrencyException) { return IdentityResult.Failed(ErrorDescriber.ConcurrencyFailure()); }
所以你需要重构代码。删除整个 catch
块,并在 else
子句中检查并发错误,如果是,则使用 UserManager.FindByIdAsync
获取当前(数据库)数据并执行您的逻辑。
像这样:
else
{
var concurrencyError = result.Errors.FirstOrDefault(error =>
error.Code == nameof(IdentityErrorDescriber.ConcurrencyFailure));
if (concurrencyError != null)
{
var dbUser = await userManager.FindByIdAsync(user.Id);
// Check for null(deleted) or modified properties here
}
}