使用 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
考虑一个场景,您正在尝试对银行交易的日志记录进行建模。交易有金额、类型(贷方或借方)并与账户相关联。
在添加新的银行交易的情况下,我可以这样做,而且效果很好:
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