SLICK 3.0 - 多个查询相互依赖 - db.run(action) [英] SLICK 3.0 - multiple queries depending on one another - db.run(action)

查看:58
本文介绍了SLICK 3.0 - 多个查询相互依赖 - db.run(action)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Slick 3 的新手,到目前为止我已经了解 db.run 是异步调用.一旦 Future 返回,.map 或 .flatMap 就会运行.

I am new to Slick 3 and so far I have understood that db.run are asynchronous call. the .map or .flatMap is run once the Future is returned.

我下面代码中的问题是所有子查询都不起作用(嵌套的 db.run).

The problem in my code below is that all the sub queries do not work (nested db.run).

从概念上讲,我没有得到什么?执行以下这种代码是否有效?基本上在第一个查询的 .map 中,我根据第一个查询执行一些操作.

Conceptually speaking, what am I not getting? Is it valid to do this kind of code as below? basically in the .map of the first query I do some actions depending on the first query.

我到处都看到带yield的for循环,这是唯一的出路吗?我的代码中的问题是否与返回的 Future 值有关?

I see everywhere for loops with yield, is it the only way to go? Is the problem in my code related to the returned Future value?

val enterprises = TableQuery[Enterprise]
val salaries = TableQuery[Salary]

//Check if entered enterprise exists 
val enterpriseQS = enterprises.filter(p => p.name.toUpperCase.trim === salaryItem.enterpriseName.toUpperCase.trim).result

val result=db.run(enterpriseQS.headOption).map(_ match 
{
    case Some(n) => {
      //if an enterprise exists use the ID from enterprise (n.id) when adding a record to salary table
      val addSalary1 = salaries += new SalaryRow(0, n.id, salaryItem.worker)
      db.run(addSalary1)
    }
    case None =>  {
        //if an enterprise with salaryItem.enterpriseName doesn't exist, a new enterprise is inserted in DB
        val enterpriseId = (enterprises returning enterprises.map(_.id)) += EnterpriseRow(0, salaryItem.enterpriseName)
        db.run(enterpriseId).map{
            e => {
                val salaryAdd2 = salaries += new SalaryRow(0, e, salaryItem.worker)
                db.run(salaryAdd2)
            }
        }
    }
})

推荐答案

我下面代码中的问题是所有子查询都不起作用(嵌套db.run)

The problem in my code below is that all the sub queries do not work (nested db.run)

我怀疑您最终会得到嵌套的 Future[R] 结果.我没有调查过.因为……

I suspect you're ending up with nested Future[R] results. I've not investigated that though. Because...

从概念上讲,我没有得到什么?

Conceptually speaking, what am I not getting?

我解决这个问题的方法是结合DBIO[R].这可能是有用的概念.

The way I'd tackle this is to look at combining DBIO[R]. That might be the concept that helps.

您正在做的是尝试单独运行每个操作(查询、插入...).相反,将单个动作组合成一个动作并运行它.

What you're doing is trying to run each action (query, insert...) individually. Instead, combine the individual actions into a single action and run that.

我会重新编写主要逻辑如下:

I'd re-write the main logic as this:

  val action: DBIO[Int] = for {
    existingEnterprise <- enterpriseQS.headOption
    rowsAffected       <- existingEnterprise match {
      case Some(n) => salaries += new SalaryRow(0, n.id, salaryItem.worker)
      case None    => createNewEnterprise(salaryItem)
    }
  } yield rowsAffected

对于 None 的情况,我会创建一个辅助方法:

For the None case I'd create a helper method:

  def createNewEnterprise(salaryItem: SalaryItem): DBIO[Int] = for {
    eId          <- (enterprises returning enterprises.map(_.id)) += EnterpriseRow(0, salaryItem.enterpriseName)
    rowsAffected <- salaries += new SalaryRow(0, eId, salaryItem.worker)
  } yield rowsAffected

最后,我们可以运行:

  val future: Future[Int] = db.run(action)
  // or db.run(action.transactionally)    

  val result = Await.result(future, 2 seconds)

  println(s"Result of action is: $result")

我写的博文的后半部分 更多地谈论这个.

我使用的代码是:https://github.com/d6y/so-31471590

这篇关于SLICK 3.0 - 多个查询相互依赖 - db.run(action)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆