【问题标题】:How to insert main and detailed data at once by ecto如何通过ecto一次插入主要和详细数据
【发布时间】:2020-04-24 05:26:53
【问题描述】:

我有主要数据和详细数据。我想同时插入两个。

-------
 main
-------
 id
 name
-------

---------
 detail
---------
 id
 main_id
 name
---------

我正在使用 ecto 的多交易。 但是我不知道如何一次插入。

main = [name: "zaku"]
details = [%{main_id: 1, name: "hoge"}, %{main_id: 1, name: "moja"},]

Multi.new()
  |> Multi.insert(:main, Main.changeset(%Main{}, main))
  |> Multi.insert(:detail, Detail.changeset(%Detail{}, details))
  |> Repo.transaction()

细节插入中的部分不起作用。 我该怎么办?

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    孩子的插入不起作用因为事务。当尝试插入Detail 时,父级还不存在。

    通常使用Ecto.build_assoc/3 插入依赖记录,或者[不推荐!]您可能会摆脱事务并通过两个查询一个一个地插入它们 - 这会起作用。

    【讨论】:

      【解决方案2】:

      我认为您这里的示例类似于the solution for your other example,您只需要通过调用transaction/1 函数来关闭多个查询:

      alias Ecto.Multi
      alias Ecto.Repo
      
      user = get_user_params_from_form() # <-- or where-ever you are getting data
      email = get_email_params_from_form()
      
      Multi.new()
          |> Multi.insert(:user, User.changeset(%User{}, user))
          |> Multi.insert(
            :email,
            # Capture the id from the previous operation
            fn %{
                 user: %User{
                   id: user_id
                 }
               } ->
              Email.changeset(%Email{user_id: user_id}, email)
            end
          )
          |> Repo.transaction()
      

      就我个人而言,我不觉得Multi 的东西很容易使用,所以有时我更喜欢这种其他语法,您可以在其中将函数传递给Repo.transaction/2 callback。粗略地说,它看起来像这样:

      Repo.transaction(fn ->
        with {:ok, thing1} <- create_thing1(attrs1) do
          create_thing2(attrs2)
        else
          {:error, e} -> Repo.rollback(e)
        end
      end)
      
      
      def create_thing1(attrs \\ %{}) do
        %ThingOne{}
        |> ThingOne.changeset(attrs)
        |> Repo.insert()
      end
      
      def create_thing2(attrs \\ %{}) do
        %ThingTwo{}
        |> ThingTwo.changeset(attrs)
        |> Repo.insert()
      end
      

      需要指出的是,这种模式可以用来将任何任务包装在一个事务中。例如。例如,如果“thing2”要与第 3 方 API 交互。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-20
        • 2012-07-21
        • 2018-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-02
        • 1970-01-01
        相关资源
        最近更新 更多