11

私は Slick 3 が初めてで、これまでのところ db.run が非同期呼び出しであることを理解しています。Future が返されると、.map または .flatMap が実行されます。

以下のコードの問題は、すべてのサブクエリが機能しないことです (ネストされた db.run)。

概念的に言えば、何が得られないのでしょうか? この種のコードを以下のように実行することは有効ですか? 基本的に、最初のクエリの .map で、最初のクエリに応じていくつかのアクションを実行します。

yield を使用した for ループがどこにでもありますが、それが唯一の方法ですか? 私のコードの問題は、返された Future 値に関連していますか?

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)
            }
        }
    }
})
4

1 に答える 1

15

以下の私のコードの問題は、すべてのサブクエリが機能しないことです (ネストされた db.run)

ネストされたFuture[R]結果になってしまうのではないかと思います。そこまでは調べていませんが。なぜなら...

概念的に言えば、何が得られないのでしょうか?

私がこれに取り組む方法は、結合を見ることDBIO[R]です。それが役立つ概念かもしれません。

あなたがしていることは、各アクション(クエリ、挿入...) を個別に実行しようとしていることです。代わりに、個々のアクションを 1 つのアクションに結合して実行します。

主なロジックを次のように書き直します。

  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場合、ヘルパー メソッドを作成します。

  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

于 2015-07-18T10:06:10.170 に答える