首页 > 解决方案 > 持久的“upsert”不起作用

问题描述

我显然对 Persistent 的upsert功能以及它如何与 Postgres 9.5 一起工作感到困惑。

我正在编写一个 Yesod 应用程序,它接受一个 JSON 值,解析它,然后upsert在适当的数据库表上执行一个。我已经验证 JSON 被解析为有效值。见代码:

postITSClientsR :: Handler TypedContent
postITSClientsR = do
  i <- requireJsonBody :: Handler IntensiveTreatmentClient
  row <- runDB $ upsert i []
  selectRep . provideJson $ row

我还验证了此模型类型具有唯一性约束:

IntensiveTreatmentClient json
  clientId ClientId
  UniqueIntensiveTreatmentClientClientId clientId
  etc...

但是,我的新价值没有得到保存。我已经验证了几次,但 Yesod 日志可能是最能说明问题的,因为它报告:

POST /api/itsClients
  Params: [("{\"clientId\":1,...","")]
  Request Body: {"clientId":1,...}
  Accept: */*
  Status: 200 OK 0.005041s

(字段已被故意删除以匿名化)通常,日志会报告已运行的 SQL 查询,而这不会报告任何内容。

到底是怎么回事?Yesod 或 Persistent 只是默默地删除我的查询,没有错误。

标签: haskellyesod

解决方案


我认为 upsert 评论是错误。我打开拉取请求添加:PersistentTest: upsert 失败,它期望由 ncaq 等效 repsert · 拉取请求 #821 · yesodweb/persistent

upsert 当两个参数列表为空时不更新。

如果你想要唯一的 repsert。此代码由我创建,您可以使用堆栈溢出 cc 许可证。

-- | if a record exist by unique, then 'replace', else 'insert'
repsertBy :: ( PersistEntityBackend record ~ BaseBackend backend
             , PersistStoreWrite backend
             , PersistEntity record
             , PersistUniqueRead backend
             , MonadIO m) =>
             record -> ReaderT backend m (Key record)
repsertBy record = do
    me <- getByValue record
    case me of
        Nothing             -> insert record
        Just (Entity key _) -> replace key record >> return key

但是,此代码在 Yesod 主流中被拒绝。因为,当存在多个唯一常量时,则未定义。


推荐阅读