使用 Persistent 输入与数据库的关系
Posted
技术标签:
【中文标题】使用 Persistent 输入与数据库的关系【英文标题】:Entering relations to database using Persistent 【发布时间】:2015-09-09 18:49:13 【问题描述】:从 Haskell 和 Yesod 开始,相对于 Haskell,Yesod 可能有点过分了:)
我使用 Persistent via 构建实体
share [mkPersist sqlSettings, mkMigrate "migrateAll"][persistLowerCase|
Game
title String
company String
UniqueTitle title
deriving Show
Tag
label String
description String Maybe
UniqueLabel label
deriving Show
GameTag
gameId GameId
tagId TagId
UniqueGameTag gameId tagId
|]
-- Yesod related code ...
我主要有
main :: IO ()
main = do
let taggings = fromFile :: [(Game, Tag)] -- fromFile code not included
runStderrLoggingT $ withSqlitePool ":inmemory:" 10 $ λpool → liftIO $ do
runResourceT $ flip runSqlPool pool $ do
runMigration migrateAll
let (g, t) = head taggings
gid ← insert g
tid ← insert t
insert (GameTag gid tid)
warp 3000 $ App pool
这样做,我将第一个关系放入数据库,通过从列表中选择元素,我可以“手动”添加更多元素,但我无法弄清楚如何通过以某种方式迭代将所有关系放入数据库taggings
。如何定义一个可以映射到taggings ::[(Game, Tag)]
的函数并插入构造的GameTag
类型的游戏标签
由持久?
【问题讨论】:
【参考方案1】:这里的主要技巧不是拉出函数,这很简单:
f (g, t) = do
gid <- insert g
tid <- insert t
insert (GameTag gid tid)
诀窍是知道如何使用它....标准map
不能单独工作,因为该函数是在 monad 中定义的(你可以使用它,它只会给你一个动作列表,而无需运行它们)。
map f taggings -- returns just a list, type [ResourceT IO a], doesn't run anything
这里有两种从 main 中实际运行操作的方法。
sequence (map f taggings) --sequentially runs the actions in the list
或者,更易读
forM taggings f
或者,稍微详细一点
forM taggings $ \tagging -> do
f tagging
您可能还想查看mapM
。还应该了解forM_
和sequence_
以抑制(通常是无用的)返回值。
【讨论】:
以上是关于使用 Persistent 输入与数据库的关系的主要内容,如果未能解决你的问题,请参考以下文章
获取 Persistent Storage 中的 MappingResult firstObject 值,避免出现“非法建立关系”错误