2017-09-16 2 views
1

J'ai le modèle DB suivant utilisé avec sequelize et essayer d'insérer plusieurs balises à un lien donné:Sequelize contrainte de clé étrangère sur promesse traitée insert/créer

const Tag = hnd.define('tag', { 
    name: { 
     type: Sequelize.STRING, 
     allowNull: false, 
     primaryKey: true, 
    }, 
}); 

const Link = hnd.define('link', { 
    title: { 
     type: Sequelize.STRING, 
     allowNull: false, 
    }, 
    description: { 
     type: Sequelize.STRING, 
     allowNull: false, 
    }, 
    url: { 
     type: Sequelize.STRING, 
     allowNull: false, 
    }, 
    votes: { 
     type: Sequelize.INTEGER, 
     allowNull: false, 
    }, 
}); 

Link.belongsToMany(Tag, {through:'link_tag', foreignKey: 'tag_name'}); 
Tag.belongsToMany(Link, {through:'link_tag', foreignKey: 'link_id'}); 

Pour faire face à la situation dans laquelle je suis prêt à créer le lien correspondant, les balises, puis remplir le n: m

Sequelize.transaction(function (t) { 
    return Link.create({ 
     title: data.title, 
     description: data.description, 
     url: data.url, 
     votes: 0, 
    }, { transaction: t }).then(persistetLink => { 
     return Sequelize.Promise.map(req.body.tags, function (tag) { 
      return Tag.findOrCreate({ where: { name: tag.text }, transaction: t }).then(function (persistedTag) { 
       return persistetLink.addTag(persistedTag, { transaction: t }); 
      }); 
     }); 
    }); 

Lorsque l'on regarde à la sortie DB Je suis face à un Unhandled rejection SequelizeForeignKeyConstraintError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed

Parce que le lien ne sera pas inséré avant que la relation link_tag sera remplie.

Y a-t-il des indications sur la façon de gérer cette situation?

Sortie de l'enregistrement est:

2017-09-16T09:37:04.554Z - info: Connection has been established successfully. 
Executing (default): PRAGMA INDEX_INFO(`sqlite_autoindex_tags_1`) 
Executing (default): CREATE TABLE IF NOT EXISTS `links` (`id` INTEGER PRIMARY KEY AUTOINCREMENT, `title` VARCHAR(255) NOT NULL, `description` VARCHAR(255) NOT NULL, `url` VARCHAR(255) NOT NULL, `votes` INTEGER NOT NULL, `createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL); 
Executing (default): PRAGMA INDEX_LIST(`links`) 
Executing (default): CREATE TABLE IF NOT EXISTS `link_tag` (`createdAt` DATETIME NOT NULL, `updatedAt` DATETIME NOT NULL, `tag_name` INTEGER NOT NULL REFERENCES `links` (`id`) ON DELETE CASCADE ON UPDATE CASCADE, `link_id` VARCHAR(255) NOT NULL REFERENCES `tags` (`name`) ON DELETE CASCADE ON UPDATE CASCADE, PRIMARY KEY (`tag_name`, `link_id`)); 
Executing (default): PRAGMA INDEX_LIST(`link_tag`) 
Executing (default): PRAGMA INDEX_INFO(`sqlite_autoindex_link_tag_1`) 
Executing (152f0ee9-43ae-40e2-bf2d-0ee3d002b80e): BEGIN DEFERRED TRANSACTION; 
Executing (152f0ee9-43ae-40e2-bf2d-0ee3d002b80e): INSERT INTO `links` (`id`,`title`,`description`,`url`,`votes`,`createdAt`,`updatedAt`) VALUES (NULL,'Heise','IT News','http://www.heise.de',0,'2017-09-16 09:37:13.250 +00:00','2017-09-16 09:37:13.250 +00:00'); 
Executing (152f0ee9-43ae-40e2-bf2d-0ee3d002b80e): COMMIT; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): BEGIN DEFERRED TRANSACTION; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SAVEPOINT `07ff716e-c00d-47c9-b54f-2af91bf58f32-savepoint-1`; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SAVEPOINT `07ff716e-c00d-47c9-b54f-2af91bf58f32-savepoint-2`; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SAVEPOINT `07ff716e-c00d-47c9-b54f-2af91bf58f32-savepoint-3`; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SELECT `name`, `createdAt`, `updatedAt` FROM `tags` AS `tag` WHERE `tag`.`name` = 'it'; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SELECT `name`, `createdAt`, `updatedAt` FROM `tags` AS `tag` WHERE `tag`.`name` = 'news'; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SELECT `name`, `createdAt`, `updatedAt` FROM `tags` AS `tag` WHERE `tag`.`name` = 'heise2'; 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): INSERT INTO `tags` (`name`,`createdAt`,`updatedAt`) VALUES ('it','2017-09-16 09:37:13.287 +00:00','2017-09-16 09:37:13.287 +00:00'); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): INSERT INTO `tags` (`name`,`createdAt`,`updatedAt`) VALUES ('heise2','2017-09-16 09:37:13.287 +00:00','2017-09-16 09:37:13.287 +00:00'); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): INSERT INTO `tags` (`name`,`createdAt`,`updatedAt`) VALUES ('news','2017-09-16 09:37:13.291 +00:00','2017-09-16 09:37:13.291 +00:00'); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SELECT `createdAt`, `updatedAt`, `tag_name`, `link_id` FROM `link_tag` AS `link_tag` WHERE `link_tag`.`tag_name` = 1 AND `link_tag`.`link_id` IN ('it', 1); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SELECT `createdAt`, `updatedAt`, `tag_name`, `link_id` FROM `link_tag` AS `link_tag` WHERE `link_tag`.`tag_name` = 1 AND `link_tag`.`link_id` IN ('heise2', 1); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): SELECT `createdAt`, `updatedAt`, `tag_name`, `link_id` FROM `link_tag` AS `link_tag` WHERE `link_tag`.`tag_name` = 1 AND `link_tag`.`link_id` IN ('news', 1); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): INSERT INTO `link_tag` (`createdAt`,`updatedAt`,`tag_name`,`link_id`) VALUES ('2017-09-16 09:37:13.304 +00:00','2017-09-16 09:37:13.304 +00:00',1,'it'),('2017-09-16 09:37:13.304 +00:00','2017-09-16 09:37:13.304 +00:00',1,1); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): INSERT INTO `link_tag` (`createdAt`,`updatedAt`,`tag_name`,`link_id`) VALUES ('2017-09-16 09:37:13.305 +00:00','2017-09-16 09:37:13.305 +00:00',1,'heise2'),('2017-09-16 09:37:13.305 +00:00','2017-09-16 09:37:13.305 +00:00',1,1); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): INSERT INTO `link_tag` (`createdAt`,`updatedAt`,`tag_name`,`link_id`) VALUES ('2017-09-16 09:37:13.310 +00:00','2017-09-16 09:37:13.310 +00:00',1,'news'),('2017-09-16 09:37:13.310 +00:00','2017-09-16 09:37:13.310 +00:00',1,1); 
Executing (07ff716e-c00d-47c9-b54f-2af91bf58f32): ROLLBACK; 
Unhandled rejection SequelizeForeignKeyConstraintError: SQLITE_CONSTRAINT: FOREIGN KEY constraint failed 
    at Query.formatError (C:\DEV\git\linklist\node_modules\sequelize\lib\dialects\sqlite\query.js:374:18) 
    at Statement.afterExecute (C:\DEV\git\linklist\node_modules\sequelize\lib\dialects\sqlite\query.js:119:32) 
    at Statement.replacement (C:\DEV\git\linklist\node_modules\sqlite3\lib\trace.js:19:31) 

Répondre

0

Eh bien, je viens de faire un cerveau décompiler rapide de votre code ... basé sur mon expérience antérieure avec ce joli cadre, de son mieux pour faire le Promise.map/ tous les appels d'abord puis les promesses uniques.

Ainsi, il peut être juste ReOrdering essentiellement vos inserts:

Sequelize.transaction(function(t) { 
    return Sequelize.Promise.map(req.body.tags, function (tag) { 
     return Tag.findOrCreate({ where: { name: tag.text }, transaction: t }); 
    }).then(function(values) { 
     return Link.create({ 
      title: data.title, 
      description: data.description, 
      url: data.url, 
      votes: 0, 
     }, { transaction: t }).then(function(link) { 
      return Sequelize.Promise.map(values, function(value) { 
       return link.addTag(value[0], { transaction: t }); 
      }); 
     }); 
    }); 
}); 

S'il vous plaît pas que je n'ai pas une véritable explication pourquoi cela est la façon dont il est. J'utilise la fonction de réponse pour montrer une solution de travail ...