在单个事务中从与给定架构的建筑关联中插入外键

时间:2019-06-24 11:38:46

标签: elixir schema ecto phoenix

我有一个架构exchange_accountsuser_profile user_profile有一个来自exchange_accounts_id模式的Foreign_key列exchange_accounts。我想在需要将user_profileexchange_accounts_id表的主键列关联的exchange_accounts表中插入数据。

我有create_user_profile功能 我尝试使用Ecto.Multi.run 现在基本上我不了解两者之间的建立联系。

def create_user_profile(profile_info, dealer_id) do
   Ecto.Multi.new()
    |> Ecto.Multi.run(:exchange, fn %{exchange: exchange} -> Ecto.build_assoc(exchange, :user_profile)
    |> Ecto.Multi.insert(:user, UserProfile.changeset(%UserProfile{}, profile_info))
    |> Ecto.Multi.merge(fn %{user: user} ->
      bank_detail =
        Ecto.build_assoc(user, :bank_details)
        |> BankDetails.changeset(profile_info)

      Ecto.Multi.new()
      |> Ecto.Multi.insert(:bank_detail, bank_detail)
    end)

我想在将数据插入user_profile表中之前执行此操作 而且我尝试使用Ecto.Multi.run来执行此操作,但是它不起作用。

结果应该是应该在两个表之间建立关联,并且应该插入数据。 whenevr iam试图运行它只是不起作用。我不明白我在哪里错了,使用Ecto.Multi.run是否正确。

1 个答案:

答案 0 :(得分:1)

Ecto.Multi.run/3/5本身不会执行任何操作,您仍然需要在传递的fn/2内部执行任何操作。对于您认为成功的操作,此函数需要返回{:ok, val},或者如果您认为操作失败,则返回{:error, val},以便Ecto知道是否应回滚整个事务。

来自> Ecto 3(如果我没记错的话),Multi insertupdate等也可以接受fn/1,其中参数将是multi操作的Map到目前为止。

因此,您可能应该更改此设置: |> Ecto.Multi.run(:exchange, fn %{exchange: exchange} -> Ecto.build_assoc(exchange, :user_profile)

收件人:

|> Ecto.Multi.insert(:exchange, fn(_) -> Ecto.build_assoc(exchange, :user_profile) end)

或继续运行,但请执行以下操作:

Ecto.build_assoc(exchange, :user_profile)
|> Repo.insert()

然后在用户插入时,使用:exchange值将其放置在您的user_profile中。

|> Ecto.Multi.insert(:user, fn(%{exchange: exchange}) ->
  # now you have access to the `exchange` operation result from the previous step
  UserProfile.changeset(%UserProfile{}, profile_info)
end)

您还可以通过在传递给Repo.transaction/1的闭包内进行常规Repo.insert等操作,在fn内将所有这些作为常规代码运行。 Multi允许您显式分离每个操作,并在每个后续步骤中访问每个操作,如果认为事务成功(即使与DB操作无关),则可以做其他可能会或可能不会更改的事情,然后成功返回或以及失败的操作等,以及传递Multi结构以通过Multi.merge添加其他内容。