关于删除的phoenix ecto关系

时间:2016-10-14 21:04:53

标签: relationship phoenix-framework ecto

有两种模式:资源和元数据:

defmodule Myapp.Repo.Migrations.CreateResources do
  use Ecto.Migration

  def change do
    create table(:resources) do
      add :name, :string
      add :parent_id, references(:resources, on_delete: :delete_all)
      timestamps
    end
    create index(:resources, [:parent_id])
  end
end

defmodule Myapp.Repo.Migrations.CreateMetadata do
  use Ecto.Migration

  def change do
    create table(:metadata) do
      add :size, :integer
      add :resource_id, references(:resources)
      timestamps
    end
    create index(:metadata, [:resource_id])
  end
end

  schema "resources" do
    field :name, :string
    belongs_to :parent, Myapp.Resource
    has_one :metadata, Myapp.Metadata, on_delete: :delete_all
    has_many :childs, Myapp.Resource, foreign_key: :parent_id, on_delete: :delete_all

    timestamps()
  end

  schema "metadata" do
    field :size, :integer
    belongs_to :resource, Myapp.Resource

    timestamps()
  end

资源可以有子节点,其中parent_id = id。 还有一个资源元数据。表元数据具有resource_id列。 现在,我想删除所有孩子的资源,以及所有相关的元数据。 我写的时候

Repo.delete resource

我收到错误:

[error] #PID<0.441.0> running Myapp.Endpoint terminated
Server: localhost:4000 (http)
Request: POST /resources/%2Fdocs%2Ftest
** (exit) an exception was raised:
    ** (Postgrex.Error) ERROR (foreign_key_violation): update or delete on table "resources" violates foreign key constraint "metadata_resource_id_fkey" on table "metadata"

    table: metadata
    constraint: metadata_resource_id_fkey

Key (id)=(3) is still referenced from table "metadata".

仅在触发从资源子项中删除元数据时才会出现。如果我尝试删除没有孩子的资源,那么一切都正常。

显然,不会导致删除子项所需的回调删除元数据,因此Postgres出错。

是否可以在不遭受resource_id元数据metadata_id资源的情况下解决此问题,并且无需开始递归手动删除资源的所有子项?

1 个答案:

答案 0 :(得分:3)

除非通过数据库迁移进行设置,否则

:delete_all 不会级联到子记录。要解决此问题,请确保将元数据迁移脚本行更改为

add :resource_id, references(:resources, on_delete: :delete_all)