简体   繁体   English

为什么Scala不能找到参数scala.slick.session.Session的隐含值?

[英]Why can't Scala find implicit value for parameter scala.slick.session.Session?

I am running a Scala Play 2.2 application with Slick 1.0.1. 我正在使用Slick 1.0.1运行Scala Play 2.2应用程序。 I am trying to wrap all of my database calls into a future try, for example: 我试图将所有数据库调用包装到将来的尝试中,例如:

object DbTeachers extends Table[DbTeacher]("edu_teachers") {
...
  def insertTeacher(school: Int, userId: String)
                   (implicit ec: ExecutionContext, db: Database) = 
    future { Try { db.withSession => { implicit s: Session =>
      (DbTeachers.school ~ DbTeachers.teacher).insert(school, userId)
  }}}
}

I find that the pattern future { Try { db.withSession => { ACTUAL_CODE_GOES_HERE }}} creates clutter and I would like to abstract it out as follows: 我发现模式future { Try { db.withSession => { ACTUAL_CODE_GOES_HERE }}}会造成混乱,我想将其抽象如下:

sealed class DbAsync[T](block: => T) {
  import play.api.libs.concurrent.Execution.Implicits.defaultContext
  implicit lazy val db = Database.forDataSource(DB.getDataSource())
  def get: Future[Try[T]] = future { Try { db.withSession { implicit s: Session =>
    block 
  }}}
}

object DbAsync {
  def apply[T](block: => T): Future[Try[T]] = new DbAsync[T](block).get
}

And then I can write my insertTeacher function as: 然后我可以将insertTeacher函数编写为:

def insertTeacher(school: Int, userId: String) = DbAsync {
  (DbTeachers.school ~ DbTeachers.teacher).insert(school, userId)
}

However, the scala compiler (2.10.2) complains about this: could not find implicit value for parameter session: scala.slick.session.Session 但是,scala编译器(2.10.2)抱怨这个: could not find implicit value for parameter session: scala.slick.session.Session

According to my understanding, the insert() method does have an implicit session variable in scope within the DbAsync block, and because it is a call-by-name parameter, it shouldn't actually be evaluated until it is called within the DbAsync, at which time there would be an implicit session object in scope. 根据我的理解, insert()方法在DbAsync块中的范围内确实有一个隐式会话变量,并且因为它是一个按名称调用的参数,所以在DbAsync中调用它之前,它不应该被实际评估,此时在范围内会有一个隐式会话对象。

So, my question is, how do I convince the Scala compiler that there actually is an implicit Session object in scope? 所以,我的问题是,如何说服Scala编译器在范围内实际存在隐式Session对象?

Your suggestion is incorrect. 你的建议不正确。 It doesn't matter where call-by-name parameter will be evaluated. 在哪里评估call-by-name参数并不重要。 All implicit parameters should be resolved at compile time in the place where they are required. 所有隐式参数都应在编译时在需要它们的地方解析。

You could make it work this way: 你可以这样工作:

def dbAsync[T](block: Session => T): Future[Try[T]] = {
  import play.api.libs.concurrent.Execution.Implicits.defaultContext
  implicit lazy val db = Database.forDataSource(DB.getDataSource())
  future { Try { db.withSession { block }}}
}

def insertTeacher(school: Int, userId: String) = dbAsync { implicit s: Session =>
  (DbTeachers.school ~ DbTeachers.teacher).insert(school, userId)
}

Note that you don't need class DbAsync nor object DbAsync . 请注意,您不需要类DbAsync也不需要对象DbAsync

Note that you should not use defaultContext for blocking operations. 请注意,不应使用defaultContext进行阻止操作。 You could create additional ExecutionContext with configured thread pool. 您可以使用配置的线程池创建其他ExecutionContext

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM