【问题标题】:Under what conditions does flush() need to be invoked in an Ecto migration?在什么情况下需要在 Ecto 迁移中调用 flush()?
【发布时间】:2018-09-12 17:07:17
【问题描述】:

我正在尝试找出需要使用冲洗的情况。

作为一个反例,这种(微不足道的)情况不需要刷新:

defmodule MyRepo.Migrations.TestFlush do
  use Ecto.Migration

  def change do
    create table(:test)
    alter table(:test) do
      add :a, :integer
    end
  end
end

它分别使用ecto.migrateecto.rollback 来“向前”和“向后”工作。第二个宏“alter table”依赖于第一个宏“create table”的完成。 flush() 不需要在此处指示任何类型的同步依赖。

我正在尝试定义需要调用 flush() 才能使特定迁移成功运行的情况。

这里是 flush 的文档: https://hexdocs.pm/ecto/Ecto.Migration.html#flush/0

这是 flush 的源代码: https://github.com/elixir-ecto/ecto/blob/master/lib/ecto/migration/runner.ex#L96

请注意,flush 的源代码颠倒了“命令”,但它没有定义什么构成命令。

谢谢!

【问题讨论】:

    标签: elixir ecto phoenix


    【解决方案1】:

    您必须使用冲洗,例如当刷新后的迁移 (M2) 取决于刷新前的迁移 (M1)。需要明确的是,M1M2 都是同一个迁移文件的一部分,并且都在 change/0 中定义和执行。

    假设M1 创建一个表,将列添加到数据库并插入一些数据,这些数据是迁移代码的一部分。 M2 然后从M1 查询表和列,并生成具有相同数据的新表。那么,如果你没有在M1M2之间运行flush/0,那么你就不能对M1的列进行查询,因为还没有执行迁移。

    【讨论】:

    • 您能否更具体地了解“查询”、“M2 然后查询...”等术语。因为有多种方法可以运行查询,例如迁移宏 execute,以及 Ecto.Repo 方法。
    • 我对“M2 then 查询”的意思是M2 执行SELECT * FROM ... 并将结果数据插入到使用create table(:tableName) do ... end 生成的新表中。这是一个非常简化的示例,只是为了说明flush/0 的简单用例。你也应该看看这个线程:elixirforum.com/t/using-flush-in-ecto-migration/11720
    • 这在没有刷新的情况下工作:def change do create table(:test) alter table(:test) do add :a, :integer end execute """ select * from test; """跨度>
    • 请查看这篇文章,有一个更好的例子,但问题几乎相同:hashrocket.com/blog/posts/ecto-migrations-simple-to-complex
    • 我认为 flush() 是必需的,因为宏,altercreate,甚至是execute,都将语句推送到一个稍后会发生的事务队列中。通过使用 Ecto.Repo api 函数,这些发生在“现在”,这为时过早,因为交易尚未执行。但是,仅通过进行一些手动测试,看起来您确实可以在 execute 语句中调用任何查询,并且它应该按照您期望的顺序发生。
    猜你喜欢
    • 2011-04-19
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 2016-08-08
    • 2010-10-31
    • 1970-01-01
    • 2016-07-17
    • 1970-01-01
    相关资源
    最近更新 更多