MongoDB异步调用中存储操作状态校验及优化方案咨询
问题1:上述修改是否能够确认存储操作执行成功?
不能,存在两处明显疏漏:
- 你在await任务之后才读取
IsCompletedSuccessfully属性没有实际意义:如果任务执行过程中抛出数据库异常、被取消令牌中止,await会直接向上抛出异常,代码根本不会运行到return逻辑。只要能执行到return行,这个属性必然为true,相当于没有做任何有效校验。 - 任务执行状态成功不代表存储逻辑实际生效:比如你第一步查询到目标文档存在后,瞬间有其他请求把该文档删除,后续的
FindOneAndReplaceAsync会因为匹配不到文档没有执行任何修改,但数据库请求本身是正常完成的,Task状态仍为成功,你的判断逻辑会误返回true。
问题2:是否存在比单独声明任务再await更简洁的方式获取操作状态?
有。FindOneAndReplaceAsync的返回值本身就可以直接判断操作是否生效,不需要单独存储Task变量,还能省去你之前冗余的前置查询逻辑,避免竞态问题:
该方法返回的是被替换前的原文档对象,如果替换操作匹配到了文档并执行了更新,就会返回旧文档;如果没有匹配到任何可更新的文档,就返回null。可以直接改写为:
public async Task<bool> UpdateThingAsync(Thing thing, CancellationToken token) { var replacedOldDoc = await Things.FindOneAndReplaceAsync(x => x.Id == thing.Id, thing, null, token); return replacedOldDoc != null; }
如果需要区分「数据库请求本身失败」和「没有匹配到可更新文档」两种场景,在外层套try-catch捕获MongoDB相关异常即可,不需要手动判断Task的运行状态。
内容的提问来源于stack exchange,提问作者Konrad Viltersten
相关产品推荐
相关产品推荐

