2015-07-17 5 views
10

Ich bin neu in Slick 3 und bisher habe ich verstanden, dass db.run asynchroner Aufruf sind. Die .map oder .flatMap wird ausgeführt, sobald die Zukunft zurückgegeben wird.SLICK 3.0 - mehrere Abfragen voneinander abhängig - db.run (Aktion)

Das Problem in meinem Code unten ist, dass alle Unterabfragen nicht funktionieren (verschachtelte db.run).

Konzeptionell, was bekomme ich nicht? Ist es gültig, diese Art von Code wie unten zu tun? Grundsätzlich in der Map der ersten Abfrage mache ich einige Aktionen abhängig von der ersten Abfrage.

Ich sehe überall für Schleifen mit der Ausbeute, ist es die einzige Möglichkeit zu gehen? Bezieht sich das Problem in meinem Code auf den zurückgegebenen Future-Wert?

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) 
      } 
     } 
    } 
}) 
+0

Hallo @ user1237981 die Antwort unten Hilfe tat? Oder war es unklar? Oder habe ich den Punkt vermisst, was Sie brauchen? –

+0

Vielen Dank RIchard, es hat sofort funktioniert. Ich war im Urlaub und konnte nicht sofort antworten. – user1237981

+0

Großartig! Vielen Dank. –

Antwort

12

Das Problem in meinem Code unten ist, dass alle Unterabfragen nicht funktionieren (verschachtelte db.run)

Ich vermute, Sie endet mit verschachtelten Future[R] Ergebnissen. Ich habe das aber noch nicht untersucht. Weil ...

Vom Konzept her, was bekomme ich nicht?

Die Weise, die ich angehen würde, ist zu betrachten, DBIO[R] zu kombinieren. Das könnte das Konzept sein, das hilft.

Was Sie tun, ist versucht, jede Aktion (Abfrage, Einfügen ...) einzeln auszuführen. Kombinieren Sie stattdessen die einzelnen Aktionen zu einer einzigen Aktion und führen Sie diese aus.

Ich würde die Hauptlogik wie diese neu schreiben:

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 

Für den Fall, dass ich None eine Hilfsmethode erstellen würde:

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 
Schließlich

, können wir das laufen:

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

Die zweite Hälfte einer blog post I've written spricht mehr darüber.

Der Code, den ich verwendet habe, ist: https://github.com/d6y/so-31471590

+0

Hallo Richard, danke für deine Antwort. Es hat gut funktioniert. Ich muss nur mit diesen For-Loops trainieren. Außerdem habe ich in deinen Blog geschaut und dich inspiriert. Sehr gut gemacht. Danke noch einmal. – user1237981

Verwandte Themen