我有一个 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/

10-10 17:20
查看更多