2015-07-17 8 views
10

Sono nuovo di Slick 3 e fino ad ora ho capito che db.run è una chiamata asincrona. il .map o .flatMap viene eseguito una volta restituito il futuro.SLICK 3.0 - più query dipendenti l'una dall'altra - db.run (azione)

Il problema nel mio codice qui sotto è che tutte le sottoclassi non funzionano (nb db.run nidificato).

Concettualmente, cosa non ottengo? È valido fare questo tipo di codice come di seguito? fondamentalmente nella .map della prima query eseguo alcune azioni a seconda della prima query.

Vedo ovunque per loop con rendimento, è l'unico modo per andare? Il problema nel mio codice è correlato al valore Future restituito?

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

Hi @ user1237981 ha fatto la risposta qui sotto aiuto? O non era chiaro? O mi sono perso il punto di cui hai bisogno? –

+0

Grazie, RIchard, ha funzionato subito. Ero in vacanza e non potevo rispondere subito. – user1237981

+0

Ottimo! Grazie. –

risposta

12

Il problema nel mio codice qui sotto è che tutte le query sub non funzionano (db.run nidificato)

Ho il sospetto che stai finendo con nidificati Future[R] risultati. Non l'ho studiato però. Perché ...

Concettualmente, cosa non ottengo?

Il modo in cui vorrei affrontare questo è quello di combinare DBIO[R]. Questo potrebbe essere il concetto che aiuta.

Quello che stai facendo è cercare di eseguire ogni azione (query, inserire ...) singolarmente. Invece, unisci le singole azioni in una singola azione ed eseguila.

mi piacerebbe riscrivere la logica principale come questo:

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 

Per il caso None mi piacerebbe creare un metodo di supporto:

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 

Infine, siamo in grado di eseguire quanto segue:

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 seconda metà di uno blog post I've written parla di più.

Il codice che ho usato è: https://github.com/d6y/so-31471590

+0

Ciao Richard, grazie per la tua risposta. Ha funzionato bene. Devo solo esercitarmi con questi cicli. Inoltre ho esaminato il tuo blog e mi sono ispirato. Molto ben fatto. Grazie ancora. – user1237981

Problemi correlati