事务内:使用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
我想在创建用户时为用户创建一个钱包。理想情况下,我希望这在交易中发生,因为没有另一个可能不存在。
我想要这样的东西,在 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