将 TableQuery 对象作为参数传递会在 Slick/Scala 中导致奇怪的类型错误,但在注入时不会

问题描述

我正在编写一个函数来将一些数据保存到 Slick postgres 数据库中。这是我的表持久化 ClientRow 对象:

class ClientTable(tag: Tag) extends Table[ClientRow](tag,"clients") {
  def clientId = column[Long]("client_id",O.PrimaryKey,O.AutoInc)
  ...
  override def * =
        (clientId,phoneNumber,firstName,lastName,trainerId,dateRegistered) <> (ClientRow.tupled,ClientRow.unapply _)
}

我尝试编写以下函数,通过组合注入表和数据库依赖项:

type PersistClient[A <: AbstractTable[_]] =
    DatabaseDef => TableQuery[A] => ClientInfo => Future[ClientId]

val persist: PersistClient[ClientTable] = db =>
      clients =>
        info => {
          val action = clients.returning(
            clients.map(_.clientId) += toRow(info)
          )
          db.run(action).map(constructId(_))
    }

这里的 ClientInfo 和 ClientId 只是带有数据的案例类。 toRow 具有签名 ClientInfo => ClientRow,它将 Info 对象中的强类型/高度结构化数据转换为更原始的 sql 数据。 constructId 从 Long 中创建一个字符串 ID 以提高日志可读性(我喜欢 id.client.<number>

toRow 下,我收到以下错误

type mismatch;
 found   : messager.Client.persistence.ClientRow
 required: Long

奇怪的是,如果我在将依赖项注入包含此函数的类的同时编写相同的函数

val persistClient: ClientInfo => Future[ClientId] = info => {
      val action = clients.returning(clients.map(_.clientId)) += toRow(info)
      db.run(action).map(constructId(_))
    }

此处的 clientsdb 与之前的类型相同,但只是作为依赖项注入到类中,而不是作为函数的输入。是什么赋予了?为什么我的漂亮的柯里化代码不能编译?

解决方法

看起来 clients.returning 的参数是一个插入,返回更改的行数。这看起来不对,并且与您拥有的有效版本不同。