我有一个 Ecto 迁移,我想修改一些列,但也迁移一些数据。例如:
import Ecto.Query
defmodule MyApp.Repo.Migrations.AddStatus do
alter table(:foo) do
add(:status, :text)
end
foos = from(f in MyApp.Foo, where: ...)
|> MyApp.Repo.all
Enum.each(foos, fn(foo) ->
# There's then some complex logic here to work
# out how to set the status based on other attributes of `foo`
end)
end
现在,这里的问题是,通过调用
MyApp.Repo.all
迁移本质上使用了一个单独的数据库连接到 alter table...
语句使用的数据库连接( 编辑 :此假设是错误的,请参阅已接受的答案)。因此,没有 status
列,所以整个迁移都失败了!请注意,我们使用的是 postgres
数据库,因此 DDL 语句是事务性的。我可以将这作为两个单独的迁移或
mix
任务来设置数据,只为架构更改而迁移,但为了确保数据一致性,我宁愿不这样做。关于如何以这种方式为
MyApp.Repo
查询使用相同的数据库连接的任何想法?编辑 :注意,我正在处理一小组数据,并且在我的用例中停机是可以接受的。如果情况并非如此,请参阅下面 José 的回复以获取一些好的建议。
最佳答案
您可以通过调用 Ecto.Migration.flush/0
来执行迁移中当前挂起的更改。之后的任何代码都将具有可用的状态字段。
defmodule MyApp.Repo.Migrations.AddStatus do
alter table(:foo) do
add(:status, :text)
end
flush()
foos = from(f in MyApp.Foo, where: ...)
|> MyApp.Repo.all
...
end
关于elixir - 在 Ecto 迁移中使用 Repo,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48381568/