[官网文档翻译]Flutter持久化库drift - 事务

11,170 阅读2分钟

「这是我参与11月更文挑战的第28天,活动详情查看:2021最后一次更文挑战」。

Flutter持久化库drift(原moor)官方文档翻译汇总 - 掘金 (juejin.cn)

本文翻译自 drift 的 官方文档 Transactions (simonbinder.eu)

肉翻多有不足,不吝赐教。


重要通知: moor 已改名为 drift 。更多信息[中文]。

事务

原子性地运行多语句。

drift 已经支持事务,允许多语句原子性运行。所以直到事务完成,它们的变化对于主数据库来说是不可见的。要开始一个事务,在数据库或 DAO 上调用 transcation 方法。它接收一个函数作为参数,这个函数会以事务的方式运行。在下面的例子中,要做一个删除 category 的处理,会移动这个 category 的所有的 todo 实例回到默认的 category 中:

Future deleteCategory(Category category) {
  return transaction(() async {
    // 首先,移动受影响的 todo 实体回到默认的 category。
    await customUpdate(
      'UPDATE todos SET category = NULL WHERE category = ?',
      updates: {todos},
      variables: [Variable.withInt(category.id)],
    );

    // 然后,删除这个 category
    await delete(categories).delete(category);
  });
}

⚠️ Gotchas(明白了)

使用事务时,有一些事情需要记在心里。

  1. await 所有调用:事务内的所有的查询必须是 await 的。内部的方法完成之后,事务会跟着完成。不使用 await 的话,一些查询可能会在事务已经关闭之后还在操作。这会导致数据丢失或运行时崩溃。

  2. 流查询的不同行为:在 transaction 回调中,流查询的行为有所不同。如果正在事务内部创建流,确认下面一段内容看下它们的行为方式。

事务和查询流

在事务外已经创建的查询流和事务中创建的更新会很好的协作:所有表的变化只会在事务完成之后被报告。事务内部的更新不会即时影响流,所以数据会保持一致,也没有不必要的更新。

transaction 块中创建的流(或嵌套调用),会是另外一个故事。显然它们会:

  • 即时反映事务中发生的变化
  • 会在事务完成时完成。

如果在事务中正要折叠(collapse:折叠?毁坏?)流时,这个行为是有用的。例如:调用 firstfold。无论如何,还是建议在事务 内部 创建的流不去监听在事务 外部 的流。如果这是可能的,它会使事务的隔离原则失效,因为它的状态通过流被暴露了。