TL;博士
注:這不是一個新的答案,只闡述由阿爾Stracquadanio提供了答案。它被寫爲答案,以便更友好地顯示更多細節。
起初,我嘗試以下的版本,這是簡單地將艾度的提示結果:
def ensureTables[P <: JdbcProfile]
(profile: P)
(db: profile.api.Database, ts: Seq[TableQuery[_]]) {
import profile.api._
val ts0 = Await.result(db.run(MTable.getTables), Duration.Inf)
val ns = Set() ++ ts0.map(t => t.name.name)
for (t <- ts) Await.result(db.run(t.schema.create), Duration.Inf)
}
錯誤仍然存在,作爲ts
類型是錯誤的:由tableQueryToTableQueryExtensionMethods
需要的類型Query[T, U, Seq] with TableQuery[T]
,而不是TableQuery[_]
,所以沒有暗示符合上述定義。
的ensureTables
正確的版本應該被實現爲這樣:
def ensureTables[P <: RelationalProfile, T <: RelationalProfile#Table[_], C[_]]
(profile: P)
(db: profile.api.Database,
ts: Seq[Query[T, _, C] with TableQuery[T]]) {
import profile.api._
val ts0 = Await.result(db.run(MTable.getTables), Duration.Inf)
val ns = Set() ++ ts0.map(t => t.name.name)
for (t <- ts) Await.result(db.run(t.schema.create), Duration.Inf)
}
這個功能本身編譯。然而,當我試圖把幾個TableQuery
值加在一起並使用它,我有兩個新的錯誤:
ensureTables(profile)(db, Seq(circles, rectangles))
導致
[error] SlickProg.scala:40: no type parameters for method ensureTables: (db: slick.driver.SQLiteDriver.profile.api.Database, ts: Seq[slick.driver.SQLiteDriver.api.Query[T, _, C] with slick.driver.SQLiteDriver.api.TableQuery[T]])Unit exist so that it can be applied to arguments (slick.driver.SQLiteDriver.backend.DatabaseDef, Seq[slick.lifted.TableQuery[_ >: slab.Rectangles with slab.Circles <: slick.driver.SQLiteDriver.Table[_ >: (Int, Double, Double, Double, Double, Double) with (Int, Double, Double, Double) <: Product with Serializable]]])
[error] --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error] found : Seq[slick.lifted.TableQuery[_ >: slab.Rectangles with slab.Circles <: slick.driver.SQLiteDriver.Table[_ >: (Int, Double, Double, Double, Double, Double) with (Int, Double, Double, Double) <: Product with Serializable]]]
[error] required: Seq[slick.driver.SQLiteDriver.api.Query[?T, _, ?C] with slick.driver.SQLiteDriver.api.TableQuery[?T]]
[error] (which expands to) Seq[slick.lifted.Query[?T, _, ?C] with slick.lifted.TableQuery[?T]]
[error] ensureTables(profile)(db, Seq(circles, rectangles))
[error] ^
[error] SlickProg.scala:40: type mismatch;
[error] found : Seq[slick.lifted.TableQuery[_ >: slab.Rectangles with slab.Circles <: slick.driver.SQLiteDriver.Table[_ >: (Int, Double, Double, Double, Double, Double) with (Int, Double, Double, Double) <: Product with Serializable]]]
[error] required: Seq[slick.driver.SQLiteDriver.api.Query[T, _, C] with slick.driver.SQLiteDriver.api.TableQuery[T]]
[error] (which expands to) Seq[slick.lifted.Query[T, _, C] with slick.lifted.TableQuery[T]]
[error] ensureTables(profile)(db, Seq(circles, rectangles))
[error] ^
[error] two errors found
這是由於將不同類型的值到一個單一的序列導致出乎意料的鍵入順序。編譯器計算序列元素的通用類型(_ >: slab.Rectangles with slab.Circles <: slick.driver.SQLiteDriver.Table[_ >: (Int, Double, Double, Double, Double, Double) with (Int, Double, Double, Double) <: Product with Serializable]
)。
我結束了下面的實現,以表從ensureTable
功能外遍歷:
def ignore[T](x: T): Unit =()
def valueOf[T](f: Future[T]): T = Await.result(f, Duration.Inf)
def ensureTable[P <: RelationalProfile, T <: RelationalProfile#Table[_], C[_]]
(p: P)
(db: p.api.Database, ns: Set[String],
t: Query[T, _, C] with TableQuery[T]) {
import p.api._
val n = t.shaped.value.tableName
if (!ns.contains(n))
ignore(valueOf(db.run(t.schema.create)))
}
def tablesOf[P <: RelationalProfile](p: P)(db: p.api.Database): Seq[MTable] =
valueOf(db.run(MTable.getTables))
val names = Set() ++ tablesOf(profile)(db).map(_.name.name)
for (t <- Seq(circles, rectangles)) ensureTable(profile)(db, names, t)
謝謝阿爾Stracquadanio。
嗨Aldo,我試過這種解決方案,但它沒有奏效。然而,評論似乎不適合描述我所看到的內容,所以我在下面的答案中寫下了詳細信息。 – user2595776
嗨阿爾多,經過一番調查後我終於解決了這個問題。我仍然會寫詳細信息,但您的解決方案是正確的。 – user2595776