【问题标题】:Ecto delete many_to_many join whilst keeping joined records in tactEcto 删除 many_to_many 连接,同时保持连接记录完整
【发布时间】:2019-03-05 19:36:47
【问题描述】:

我有两个 Ecto 模型:User 和 Skill,它们通过 users_skills 表与 many_to_many 关联:

create table(:users_skills, primary_key: false) do
  add :user_id, references(:users, on_delete: :nothing)
  add :skill_id, references(:skills, on_delete: :nothing)
end

create unique_index(:users_skills, [:user_id, :skill_id])

在User 架构中有:

many_to_many :skills, Skill, join_through: "users_skills"

在Skill 架构中有:

many_to_many :users, User, join_through: "users_skills"

我想要做的是删除用户的技能而不删除User 或Skill 本身。目前我正在尝试这个:

query = Ecto.assoc(current_user, :skills)
Repo.delete_all(query)

但是它会抛出错误:

(foreign_key_violation) update or delete on table "skills" violates foreign key constraint "users_skills_skill_id_fkey" on table "users_skills"

将on_delete: :delete_all 添加到users_skills 迁移时,会产生删除关联技能的不良影响。

我该如何解决这个问题,以便在 User 和 Skill 保持完整的情况下仅删除关联记录?

【问题讨论】:

    标签: database ecto elixir


    【解决方案1】:

    我确信有更好的方法可以做到这一点,但您可以在架构中将 on_replace: :delete 选项传递给 many_to_many 宏。

    defmodule User do
      use Ecto.Schema
    
      schema "users" do
        field(:name)
        many_to_many(:skills, Skill, join_through: "users_skills", on_replace: :delete)
    
        timestamps()
      end
    end
    

    现在如果你运行

    current_user
    |> Repo.preload(:skills)
    |> Ecto.Changeset.change()
    |> Ecto.Changeset.put_assoc(:skills, [])
    |> Repo.update!()
    

    它从users_skills 表中删除,skills 表将保持不变。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多