[英]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.