SLICK 3.0-plusieurs requêtes dépendant l'une de l'autre-db.exécuter(action)

je suis nouveau à Slick 3 et jusqu'à présent j'ai compris que db.les appels sont asynchrones. le. carte ou .flatMap est lancé une fois que le futur est retourné.

le problème dans mon code ci-dessous est que toutes les requêtes secondaires ne fonctionnent pas (db imbriquée.exécuter.)

Sur le plan conceptuel, qu'est-ce que je ne comprends pas? Est-il valable pour faire ce genre de code comme ci-dessous? essentiellement dans le .carte de la première requête je fais des actions selon la première requête.

je vois partout pour boucles avec rendement, est-il le seul moyen d'aller? Le problème dans mon code est-il lié à la valeur future retournée?

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)
            }
        }
    }
})
11
demandé sur user1237981 2015-07-17 11:38:40

1 réponses

le problème dans mon code ci-dessous est que toutes les requêtes secondaires ne fonctionnent pas (db imbriquée.exécuter)

je soupçonne que vous êtes en terminant avec imbriqué Future[R] les résultats. Je n'ai pas étudié. Parce...

D'un point de vue conceptuel, qu'est-ce que je ne comprends pas?

La façon dont je voudrais aborder cette est de chercher à combiner DBIO[R]. C'est peut-être le concept qui aide.

ce que vous faites, c'est essayer d'exécuter chacun action (requête insert...) individuellement. Au lieu de cela, combinez les actions individuelles en une seule action et exécutez cela.

j'avais ré-écrire la logique principale comme ceci:

  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

pour le None cas j'aimerais créer une méthode d'aide:

  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

Enfin, nous pouvons l'exécuter:

  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")

La seconde moitié d'un blog que j'ai écrit. parle plus à ce sujet.

le code que j'ai utilisé est: https://github.com/d6y/so-31471590

14
répondu Richard Dallaway 2015-07-18 10:06:10