Yesod中的复合主键
Posted
技术标签:
【中文标题】Yesod中的复合主键【英文标题】:Composite Primary Key in Yesod 【发布时间】:2015-05-02 18:16:14 【问题描述】:我对 Haskell 还很陌生,并且已经用 yesod 试验了大约一个星期。我一直在尝试连接到在 sqlite 中具有复合主键的现有数据库。我设法让代码与 Database.Persist.Sqlite
作为独立应用程序一起使用。
这是使用 persistent-sqlite
作为独立应用程序运行的代码。
-# LANGUAGE EmptyDataDecls #-
-# LANGUAGE FlexibleContexts #-
-# LANGUAGE GADTs #-
-# LANGUAGE GeneralizedNewtypeDeriving #-
-# LANGUAGE MultiParamTypeClasses #-
-# LANGUAGE OverloadedStrings #-
-# LANGUAGE QuasiQuotes #-
-# LANGUAGE TemplateHaskell #-
-# LANGUAGE TypeFamilies #-
-# LANGUAGE FlexibleInstances #-
-# LANGUAGE DeriveGeneric #-
import Control.Monad.IO.Class (liftIO)
import Database.Persist
import Database.Persist.Sqlite
import Database.Persist.TH
import System.Environment
import Data.Text (Text,pack)
import Data.Time (UTCTime)
share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistLowerCase|
Movie
title Text maxlen=20
year Int maxlen=11
genre Text Maybe maxlen=128
mpaa Text Maybe maxlen=16
director Text Maybe maxlen=128
actors Text Maybe maxlen=512
description Text Maybe maxlen=512
path Text Maybe maxlen=128
codec Text Maybe maxlen=32
length Int Maybe maxlen=11
poster Text Maybe maxlen=128
added UTCTime default=CURRENT_TIMESTAMP
Primary title year
deriving Show
|]
main :: IO ()
main = do
(path:args) <- getArgs
movies <- runSqlite (pack path) $ do
runMigration migrateAll
selectList [] [Desc MovieTitle]
mapM_ print movies
这是一个人为的例子,但它说明了我的观点。我想要一个由title
和year
组成的复合主键。一切都编译得很好,表是用我需要的模式创建的。当我尝试在我的 yesod 应用程序中使用上面定义的 Movie
类型和 persistent-sqlite
时,我收到以下编译时错误
Foundation.hs:35:1:
No instance for (PathPiece MovieId)
arising from a use of ‘toPathPiece’
In the first argument of ‘(:)’, namely ‘(toPathPiece dyn_apvA)’
In the second argument of ‘(:)’, namely
‘((toPathPiece dyn_apvA) : [])’
In the expression:
((Data.Text.pack "entry") : ((toPathPiece dyn_apvA) : []))
Foundation.hs:35:1:
No instance for (PathPiece MovieId)
arising from a use of ‘fromPathPiece’
In the expression: fromPathPiece
In the pattern: fromPathPiece -> Just dyn_apwt
In the pattern: (:) (fromPathPiece -> Just dyn_apwt) []
我被困在这一点上,无法自己继续。我尝试过搜索,但我只能找到一个不使用 yesod 的复合主键的工作示例。我觉得应该可以这样做,因为仅使用 persistent-sqlite
的复合主键有效。
这是Movie
类型在config/models
中的定义方式
Movie
title Text maxlen=20
year Int maxlen=11
genre Text Maybe maxlen=128
mpaa Text Maybe maxlen=16
director Text Maybe maxlen=128
actors Text Maybe maxlen=512
description Text Maybe maxlen=512
path Text Maybe maxlen=128
codec Text Maybe maxlen=32
length Int Maybe maxlen=11
poster Text Maybe maxlen=128
added UTCTime default=CURRENT_TIMESTAMP
Primary title year
deriving
【问题讨论】:
【参考方案1】:我自己并没有真正使用过复合主键功能,但这个错误对我来说是有意义的。对于任意复合键,Text
没有明显的序列化,因此持久性不会为您生成它。如果您想在 URL 中使用 MovieId
,则需要手动定义 PathPiece
实例,这只是一对用于与 Text
相互转换的函数。
【讨论】:
以上是关于Yesod中的复合主键的主要内容,如果未能解决你的问题,请参考以下文章