【问题标题】:(SOLVED) How do I force the catch exception? (or retrieve exception variable)(已解决)如何强制捕获异常? (或检索异常变量)
【发布时间】:2021-01-24 15:36:48
【问题描述】:

如何强制我的 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 语句中获取这些 db 条目值,我该怎么做?

编辑 - 解决方案: 我发现我们应该避免这种情况并处理代码中的错误,即 if-else,而不是使用 Try/catch。在 else 语句中,我发现了 Identity 使用的异常,并对其进行了处理。并获取数据库值,我使用:

var dbUser = await userManager.Users.AsNoTracking().SingleOrDefaultAsync(x =&gt; x.Id == user.Id);

通过这样做,我可以比较“dbUser”和“user”的属性。

【问题讨论】:

  • 如果抛出异常,将调用catch语句。所以,你可以throw new DbUpdateConcurrencyException();,但这似乎有点奇怪。如果您在这种情况下期望的异常没有从对UpdateAsync的调用中抛出,也许您应该跟踪代码并找出为什么您没有收到result.Succeeded
  • @RufusL 当我这样做时,我的 DbUpdateConcurrencyException ex 变量为空,无法检索我的数据库条目。和 userManager.UpdateAsync(user);失败时不会抛出异常,这就是我使用 if-else 的原因
  • 我看不出“手动”输入catch 语句对您有什么好处。我的意思是,您可以只使用throw new DbUpdateConcurrencyException,但它不会被水合,因此您不会从中获得任何有用的信息。 UserManager.UpdateAsync 返回 Task&lt;IdentityResult&gt; 的实例,IdentityResult 具有 Errors 的集合。如果result.Succeededfalse,也许你可以使用它。
  • 是的,我明白——我应该更清楚一点,我实际上并不是在提倡抛出异常,因为那没有任何意义。您已经声明它在失败时不会抛出异常,那么您为什么期望该异常呢?如果result 不是Succeeded,该类是否没有记录如何确定错误?
  • @RufusL 因为我正在尝试进行并发检查,如果 2 个人编辑 RowVersion(); 它将 100% 失败;同时 - 这就是为什么我想对 else 块中的数据库条目做一些事情

标签: c# entity-framework entity-framework-core asp.net-identity


【解决方案1】:

我明白你在追求什么,但方法完全错误。

DbUpdateConcurrencyException 是 EF Core 特定的异常,而标识是抽象框架,因此设计上的这个异常永远不会流动,因此永远不会命中 catch

按照设计,错误通过IdentityResult.Errors提供,并发问题默认通过IdenitityError.Code等于“ConcurrencyFailure”提供,可以在EF Corestore 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
    }
}

【讨论】:

  • 明白,但现在的问题是它实际上并没有检查数据库条目。我使用了你的逻辑,它显示了我对我的“用户(在这篇文章中我的代码的第 3 行)”而不是我的数据库所做的分配值。我相信 await userManager.FindByIdAsync 认为分配是数据库中的当前数据。
  • 你说得对,我忘了Update已经附加了传递的实体,所以Find只是返回它。所以你需要不同的方法,可能是直接查询userManager.Users,最终结合AsNoTracking()查询数据库值。
  • 谢谢伊万,这个成功了,并显示了数据库条目值: var dbUser = await userManager.Users.AsNoTracking().SingleOrDefaultAsync(x => x.Id == user.Id);有了这个和用户,我可以比较它们并做一些事情!
猜你喜欢
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多