ON DELETE CASCADE для нескольких внешних ключей с Sequelize

Предположим, у меня есть три модели:

  • Задача: Вещь, которую необходимо сделать, например, "вынести переработку". Можно делать много раз.
  • Список заданий: Объект, представляющий список задач и имеющий собственные метаданные.
  • ЗаписьСпискаЗадач: Связь между Task и TaskList, которая может иметь такие данные, как приоритет или кто ей назначен.

У меня настроены такие ассоциации:

Task.hasMany(TaskListEntry, {onDelete: 'cascade', hooks: true}));

TaskList.hasMany(TaskListEntry, {onDelete: 'cascade', hooks: true});

TaskListEntry.belongsTo(TaskList);
TaskListEntry.belongsTo(Task);

Это работает нормально, за исключением удаления. Когда я удаляю задачу, все связанные с ней записи TaskListEntries удаляются, как и ожидалось. Однако, когда я удаляю TaskList, связанные с ним TaskListEntries просто имеют свой внешний ключ для TaskList, установленный на null.

Кажется, что Sequelize генерирует следующую таблицу:

CREATE TABLE `TaskListEntries`(
  `id` UUID PRIMARY KEY, 
  /* some other fields here */
  `createdAt` DATETIME NOT NULL, 
  `updatedAt` DATETIME NOT NULL, 
  `TaskId` UUID REFERENCES `Tasks`(`id`) ON DELETE CASCADE ON UPDATE CASCADE, 
  `TaskListId` UUID REFERENCES `TaskLists`(`id`) ON DELETE SET NULL ON UPDATE CASCADE);

Несмотря на то, что ассоциации настроены одинаково, внешние ключи для задач и списков задач имеют разное DELETE поведение. Если я удаляю одну из ассоциаций, другая работает нормально.

Поэтому я думаю, что проблема заключается в нескольких внешних ключах с ON DELETE CASCADE, по крайней мере, в том, что касается Sequelize.

Любые мысли о том, как это исправить?

Пожалуйста, в вопросах по коду укажите минимальный воспроизводимый пример - вырезать, вставить и выполнить код; пример ввода с желаемым и фактическим выводом (включая дословные сообщения об ошибках); четкая спецификация и объяснение. Это включает в себя наименьший код, который вы можете дать, то есть код, который, как вы показываете, в порядке, расширенный кодом, который вы показываете, не в порядке. (Основы отладки.)

philipxy 25.05.2019 08:40
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
7
1
6 830
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

ты можешь попробовать

TaskListEntry.belongsTo(TaskList);
TaskListEntry.belongsTo(Task);

вместо

TaskListEntry.belongsToMany(TaskList);
TaskListEntry.belongsToMany(Task); 

Потому что, насколько я понимаю эту проблему, одна запись TaskListEntry может принадлежать только одной задаче и одному TaskList.

Или вы пытаетесь установить здесь отношения «многие ко многим»? В этом случае я не думаю, что это идеальный способ реализации.

Ах, спасибо! Мне очень жаль... Я являюсь использую .belongsTo для обоих. Я случайно разместил некоторые эксперименты в своем вопросе вместо реального кода. Извините за это, спасибо за ваш ответ в исправлении меня. Я исправил код в своем вопросе. Да, одна запись TaskListEntry связана только с одной задачей и одним списком задач. Задача может иметь несколько связанных с ней записей TaskListEntries, как и TaskList.

Brad 23.05.2019 17:26

Поправьте меня, если я ошибаюсь. Нужны ли вам как отношения принадлежности к, так и отношения hasMany? В идеале вы можете удалить ассоциации принадлежности к последним двум строкам. Я чувствую, что стоит попробовать.

sabhari karthik 23.05.2019 18:13
Ответ принят как подходящий

Мне пришлось установить allowNull:false вместо foreignKey, чтобы «КАСКАД» при удалении работал. Так что это должно быть что-то вроде этого в вашем случае:

TaskListEntry.belongsTo(TaskList, {
  onDelete: 'cascade', 
  foreignKey: { allowNull: false }    //   <-------------
  hooks: true
});

С учетом того, что ваши модели в целом аналогичны этой структуре из http://docs.sequelizejs.com/manual/associations.html#belongs-to-many-associations:

class User extends Model {}
User.init({}, { sequelize, modelName: 'user' })

class Project extends Model {}
Project.init({}, { sequelize, modelName: 'project' })

class UserProjects extends Model {}
UserProjects.init({
  status: DataTypes.STRING
}, { sequelize, modelName: 'userProjects' })

User.belongsToMany(Project, { through: UserProjects })
Project.belongsToMany(User, { through: UserProjects })

Спасибо, "сквозной" пример - это то, что мне было нужно. Я не знал, что могу добавить туда дополнительные свойства и запросить напрямую. Спасибо за помощь!

Brad 30.05.2019 06:45

Другие вопросы по теме