使用 Ecto.Multi 在同一个事务中更新一个 table 两次

Use Ecto.Multi to update a table twice in the same transaction

考虑一个场景,您正在尝试对银行交易的日志记录进行建模。交易有金额、类型(贷方或借方)并与账户相关联。

在添加新的银行交易的情况下,我可以这样做,而且效果很好:

Multi.new()
|> Multi.insert(:transaction, transaction_changeset)
|> Multi.update(:account, account_changeset)
|> Repo.transaction()

更新现有的银行交易稍微复杂一些。那是因为用户不仅可以更改金额,还可以更改帐户。更新现有交易可能意味着除了将金额添加到当前帐户之外,还要从以前的帐户中删除金额。我试过了,但我不确定如何使用 Ecto.Multi.

来表达我想做的事情
Multi.new()
|> Multi.update(:transaction, transaction_changeset)
|> Multi.update(:account, previous_account_changeset)
|> Multi.update(:account, current_account_changeset)
|> Repo.transaction()

Runtime error :account is already a member of the Ecto.Multi:

这里的问题是您使用了两次 :account 键。 来自 documentation:

Ecto.Multi makes it possible to pack operations that should be performed in a single database transaction and gives a way to introspect the queued operations without actually performing them. Each operation is given a name that is unique and will identify its result in case of success or failure.


您可以选择任何您喜欢的名称,只要它是唯一的即可。只需将您的交易更改为:

Multi.new
|> Multi.update(:transaction, transaction_changeset)
|> Multi.update(:previous_account, previous_account_changeset)
|> Multi.update(:current_account, current_account_changeset)
|> Repo.transaction