2015-05-12 4 views
3

Я использую Slick 3.0, и следующие мои коды:В Slick 3.0, как упростить вложенный `db.run`?

def registerMember(newMember: TeamMember): Future[Long] = { 

    db.run(
    teamProfileTable.filter(u => u.ID === newMember.ID).result.headOption 
).flatMap { 
    case None => Future(-1) 
    case _ => db.run(
     (teamProfileTable returning teamProfileTable.map(_.staffID)) += newMember.toTeamRecord 
    ) 
    } 
} 

Это может выглядеть нормально. Но когда есть больше уровней обратного вызова, коды могут стать трудночитаемыми. Я попытался упростить коды с помощью for-expression или andThen .. Но из-за шаблон согласования, то я могу использовать только flatMap осуществить это ..

Кто-нибудь есть идеи о том, как реорганизовать это?

+0

Вы должны комбинировать запросы, а затем только в качестве последнего шага выполнить композицию на db. Вот как я думаю, он должен работать. Если вы добавите еще какой-нибудь код, чтобы сделать runnable-пример, я мог бы дать ему попробовать с ответом. –

+0

@ pagoda_5b Спасибо! Но как объединить два запроса, если второй запрос зависит от результата первого запроса? Я думаю, что 'andThen' здесь не подходит. –

+0

@hanfeisun Вы, вероятно, должны использовать для понимания, но я не могу помочь вам, если вы не можете предоставить какой-то самосогласованный код для тестирования. Я могу только догадываться о намерении и результате вашего кода, если вы не более явны. :) –

ответ

2

Я думаю, что для понимания здесь должно быть хорошо, вам просто нужно условное обращение с Option в результате первого Future. Нечто подобное должно работать (заметьте, я не компилировать проверить это):

def registerMember(newMember: TeamMember): Future[Long] = { 

    for{ 
    r1Opt <- db.run(teamProfileTable.filter(u => u.ID === newMember.ID).result.headOption 
    r2 <- r1Opt.fold(Future.successful(-1L))(r1 => db.run((teamProfileTable returning teamProfileTable.map(_.staffID)) += newMember.toTeamRecord) 
    } yield r2 

} 

Вы можете увидеть на правой стороне fold, что у меня есть доступ к результату первого Future, если он был Some (как r1).

Я бы даже принять это шаг дальше и создать отдельные методы для ступенек для понимания, чтобы очистить вещи, например, так:

def registerMember(newMember: TeamMember): Future[Long] = { 
    def findMember = 
    db.run(teamProfileTable.filter(u => u.ID === newMember.ID).result.headOption 

    def addMember(r1Opt:Option[TeamMember]) = { 
    r1Opt.fold(Future.successful(-1L)){r1 => 
     db.run((teamProfileTable returning teamProfileTable.map(_.staffID)) += 
     newMember.toTeamRecord) 
    } 
    } 

    for{ 
    r1Opt <- findMember 
    r2 <- addMember(r1Opt) 
    } yield r2 

} 
0

Другого подход для упрощения вложенных db.runs в Slick 3.0 при запрос состоит из двух таблиц, которые могут заключаться в объединении запросов в один запрос. Joining and Zipping. Тем не менее, ОП, похоже, имеет несколько более редкий случай вложенных запросов в одной таблице, поэтому такой подход может оказаться нецелесообразным в этом конкретном случае.

val query = slickLoginInfos join slickUserLoginInfos on 
    ((l,ul) => l.id === ul.loginInfoId) 
db.run((for { (l, ul) <- query } yield (ul)).result.headOption) 
Смежные вопросы