有条件地 运行 for comprehension 中的圆滑语句

Conditionally running Slick statements in a for comprehension

给定以下 Slick 代码:

   val doUpdate = true

   val table1 = TableQuery[Table1DB]
   val table2 = TableQuery[Table2DB]
   val table3 = TableQuery[Table3DB]

   val action = (for {
          _ <- table1.filter(_.id === id).update(table1Record)
          _ <- table2.filter(_.id === id).update(table2Record)
          _ <- table3.filter(_.id === id).update(table3Record)
     } yield ()).transactionally

我只需要在变量 doUpdate 为真时更新 table2table3。这是我的尝试:

   val action = (for {
          _ <- table1.filter(_.id === id).update(table1Record)
          _ <- table2.filter(_.id === id).update(table2Record)
               if (doUpdate == true)
          _ <- table3.filter(_.id === id).update(table3Record)
               if (doUpdate == true)
     } yield ()).transactionally

这可以编译,但是当我 运行 它时,我得到以下错误 Action.withFilter failed。如何添加条件?

如您所见,如果您在 for 中使用 if,它会在下面调用 withFilter。在管道 (DBIOFutures、Tasks) 的情况下,过滤归结为是继续管道(快乐路径)还是使其失败(生成 Failure 或类似内容)。

如果你只想更新,那么你可以走if路,恢复Future。但是,这会很丑陋,因为根据您编写 case 的方式,它也可能会从您想了解的错误中恢复。

另一种方法是简单地使用 if-else 来提供不同的 DBIOAction:

(for {
  _ <- {
    if (doUpdate) conditionalAction.map(_ => ())
    else DBIOAction.successful(())
  }
} yield ()).transactionally

在您的情况下,它可能类似于:

val action = (for {
  _ <- table1.filter(_.id === id).update(table1Record)
  _ <- {
    if (doUpdate) DBIOAction.seq(
      table2.filter(_.id === id).update(table2Record),
      table3.filter(_.id === id).update(table3Record)
    )
    else DBIOAction.successful(())
  }
} yield ()).transactionally