如何在 makeApplication 函数中查询数据库

Posted

技术标签:

【中文标题】如何在 makeApplication 函数中查询数据库【英文标题】:How to querying the database inside the makeApplication function 【发布时间】:2013-05-13 08:44:08 【问题描述】:

我正在尝试在我的 Yesod 应用程序中创建一个非 Web 服务,它需要与数据库进行一些交互。在this 的帖子中,我决定将服务放在makeApplication 中。我希望我的服务在某些事情发生时返回一些值并将其存储到数据库中。因此,我想知道最好的方法是什么?

如何在 makeApplication 函数中运行runDB $ insert $ Stuff (T.pack "stuff")

编辑: 正如迈克尔建议的那样,我在 Application.hs 中创建了以下辅助函数

runDBIO conf foundation f = do
    dbconf <- withYamlEnvironment "config/postgresql.yml" (appEnv conf)
        Database.Persist.loadConfig >>=
        Database.Persist.applyEnv
    p <- Database.Persist.createPoolConfig (dbconf :: Settings.PersistConf)
    logger <- mkLogger True stdout

    runLoggingT
        (Database.Persist.runPool dbconf f p)
        (messageLoggerSource foundation logger)

在 makeApplication 中我是这样使用它的:

runDBIO conf foundation $ do
    dbid <- insert $ Stuff (T.pack "some random stuff")
    string <- get dbid
    liftIO $ print string

但是,我得到了这个编译错误:

No instance for (resourcet-0.4.5:Control.Monad.Trans.Resource.MonadResource IO)
arising from a use of 'insert'

我是否为 runPool 输入了错误的类型?或者我需要为insert 创建一个实例? 我不明白为什么 runMigration migrateAll 有效但 insert 无效。

【问题讨论】:

【参考方案1】:

您可以在the scaffolding itself 的IO monad 中看到如何运行数据库操作的演示。本质上你需要提供两条信息:如何记录查询,以及数据库连接池。您可以将该代码分解为辅助函数(例如,runDBIO),然后运行runDBIO $ insert $ Stuff $ T.pack "stuff"

【讨论】:

听起来不错,我试试看!问题,你对辅助函数的立场是什么?我一直认为这是一种反模式。 也许我们对辅助函数的定义不同。我只是指一个函数,它会排除一些常见代码,我绝对不会考虑反模式。 是的,如果它是通用代码,那么创建一个函数是非常有意义的。也许我所说的辅助函数就像在 Java 中一样,人们制作实用程序类,将许多不相关的函数放入同一个类中。 把 runResourceT 放在 runDBIO 前面解决了这个问题,感谢post。

以上是关于如何在 makeApplication 函数中查询数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何在查询中引用函数参数?

PostgreSQL:如何在函数中并行运行查询?

如何在sql server用户定义函数中循环查询结果集?

如何在变量 Oracle 函数中使用部分查询

如何在 PHP 函数中正确使用 MySQL 查询? [关闭]

如何在解析函数 GraphQL 中传递两个查询?