如何在持久性中具有模块间/包间外键约束
Posted
技术标签:
【中文标题】如何在持久性中具有模块间/包间外键约束【英文标题】:How to have inter-module / inter-package foreign key constraints in Persistent 【发布时间】:2018-03-02 21:31:22 【问题描述】:由于我们的数据库中有很多模型,其中许多都相当独立地运行,我们决定在不同的模块中定义它们。然后,我们有一个 migrateAll
函数,它以串行方式运行每个迁移。似乎我们这样做会导致 Persistent 不在模型之间创建外键约束,但我真的希望这些约束存在。
作为部分修复,我们可以将它们全部放入同一个模块中,但我们还有一个单独的包,它依赖于第一个包,它在顶部创建更多模型,同样带有一些外键。当它们之间确实只有单向依赖关系时,我们不得不将这些包合并为一个,这对我们来说真的很痛苦。
是否有任何方法可以跨模块创建外键约束?也许通过这样做,如果您迁移具有外部外键约束的模型,也会运行外部模型的迁移。避免需要按依赖顺序对迁移进行排序。
也有可能没有创建外键的原因与此设置无关,但我似乎找不到其他人遇到同样的问题,所以我假设上述是原因。
对于 MCVE:
module Foo where
share [mkPersist sqlSettings, mkMigrate "migrateFoo"] [persistLowerCase|
Foo
name String
|]
module Bar where
import Foo
share [mkPersist sqlSettings, mkMigrate "migrateBar"] [persistLowerCase|
Bar
name String
foo FooId
|]
module Models where
import Foo
import Bar
migrateAll :: Migration
migrateAll = migrateFoo *> migrateBar
运行migrateAll
会做我想做的一切,除了在Bar.foo
字段上创建外键约束。如何在保持我想要的模块化的同时获得外键约束?
【问题讨论】:
MCVE 会大大改善这个问题。 @DanielWagner 完成,谢谢! 我觉得这里添加的API解决了这个问题github.com/yesodweb/persistent/pull/791 @MaxGabriel 谢谢!唯一的问题是,找出文件系统上库依赖关系的最终位置并非易事,所以我真的需要一种方法来import
我也在构建外键的表,而不仅仅是在编译时从文本文件中读取。这是因为包的依赖项实际上创建了它们自己的表,我需要迁移这些表并创建外键。
【参考方案1】:
由于persistent-2.13.0
,现在可以使用mkPersistWith
。在你的情况下:
module Foo where
share [mkPersist sqlSettings, mkEntityDefList "fooDefs"] [persistLowerCase|
Foo
name String
|]
请注意,我使用mkEntityDefList
导出TemplateHaskell 生成的EntityDef
s 以在Bar
中使用它们:
module Bar where
import Foo
share [mkPersistWith sqlSettings fooDefs, mkEntityDefList "barDefs"] [persistLowerCase|
Bar
name String
foo FooId
|]
还要注意,我不使用帮助程序 mkMigrate
(目前使用它不适用于 mkPersistWith
,因为它会引发运行时错误)。现在可以使用migrateModels
进行迁移:
module Models where
import Foo
import Bar
migrateAll :: Migration
migrateAll = migrateModels (fooDefs ++ barDefs)
这会正确地创建ForeignRef
s,甚至更新旧的丢失。
【讨论】:
以上是关于如何在持久性中具有模块间/包间外键约束的主要内容,如果未能解决你的问题,请参考以下文章