事务内:使用inserted id作为下次插入的参考

Within transaction: Use inserted id for reference to next insertion

我想在创建用户时为用户创建一个钱包。理想情况下,我希望这在交易中发生,因为没有另一个可能不存在。

我想要这样的东西,在 Ecto 范式中。

BEGIN;
  INSERT INTO albums [...];
  INSERT INTO album_images (lastval(), image_id) [...];
COMMIT;

摘自 https://github.com/elixir-ecto/ecto/issues/2154.

如何实现?

考虑使用 Multi,最后你会将 Multi 中处理的所有内容放入 Repo.transaction()

Ecto.Multi 将帮助您组织此流程,因为 Multi.run 接受包含先前计算结果的 Multi 结构 - 这就是您可以安全使用它的原因,因为如果第一个操作失败,第二个一个也会被交易拒绝。

最好的写法是将业务操作放在单独的函数中,其中第二个接受 Multi,其名称为上一个操作的结果。

Multi.new
|> Multi.insert(:albums, insert_albums(arguments))
|> Multi.run(:album_images, AlbumImage, :insert, [])
|> Repo.transaction()

其中 AlbumImage.insert 可能看起来像:

defmodule AlbumImage do
  def insert(%{albums: albums}) do
    # code
  end
end