【问题标题】:SaveChangesAsync returns exception instead of 0 [closed]SaveChangesAsync 返回异常而不是 0 [关闭]
【发布时间】:2021-12-15 03:04:11
【问题描述】:

关于 SaveChangesAsync 方法,微软说 这是一个代表异步保存操作的任务。任务结果包含写入底层数据库的状态条目数。

据此,一些程序员使用 if 条件来检查 SaveChangesAsync 运行后受影响的行数。

这里是一个例子:How can I confirm if an async EF6 await db.SaveChangesAsync() worked as expected?

但是,如果调用 SaveChangesAsync 时发生错误会怎样?好吧,与我的预期相反,即“0 行受影响”,抛出异常,在大多数情况下,DbUpdateException

“当保存对数据库的更改失败时,DbContext 引发的异常。”

那么,一旦数据库的结果永远不会为零,为什么会有几个使用if (await context.SaveChangesAsync() > 0) 的建议,而是一个例外?

【问题讨论】:

  • 如果没有任何变化,它可能为 0,但也可能引发异常。这可能是由于并发、不匹配的架构、不符合约束的数据、检查约束错误、违反引用完整性等。这只是适当的设计,异常或内部异常通常足够详细,可以让您知道原因它失败了。
  • 尝试使用 try/catch 块捕获异常并读取内部异常。唯一/主键违规、Fk 违规等...
  • 具体看内部异常是不是真的报错

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


【解决方案1】:

那么,一旦数据库的结果永远不会为零,为什么会有几个使用if (await context.SaveChangesAsync() > 0) 的建议,而是一个例外?

首先,没有这样的官方推荐。提供它们的人不知道SaveChanges 操作的语义。当前official EF Core documentation 是:

退货
Int32
写入数据库的状态条目数。

例外情况
DbUpdateException
保存到数据库时遇到错误。

DbUpdateConcurrencyException
保存到数据库时遇到并发冲突。当保存期间意外数量的行受到影响时,会发生并发冲突。这通常是因为数据库中的数据在加载到内存后被修改了。

这是给SaveChanges的,但同样适用于Async之后的Async版本。

因此,从文档中可以看出,操作可以返回 0 并且仍然成功。这是因为智能更新(加载/修改/保存)可能不会生成数据库操作。但它仍然被保存 - 因为您没有问“请强制将其写入数据库”,而是“请确保将此数据保存到数据库”。确实,如果执行强制更新,则永远不会返回 0。但这根本不是必需的。

更重要的是,操作的成功与往常一样是由没有异常决定的。我不知道返回值的预期用途是什么——可能只是因为它是“我们可以返回”的东西。或者从 EF6 继承,然后从 ADO.NET 等继承。或者如果发生真正的数据库 CUD,则将其用于一些日志记录。谁知道。但是,确实应该使用它来检查这些(反)“建议”中的成功。

【讨论】:

    猜你喜欢
    • 2018-01-28
    • 1970-01-01
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    相关资源
    最近更新 更多