Je ne sais toujours pas comment effectuer mes migrations avec knex. Voici ce que j'ai jusqu'à présent. Cela fonctionne sur up
, mais down
me donne une erreur de contrainte FK même si foreign_key_checks = 0.
exports.up = function(knex, Promise) {
return Promise.all([
knex.raw('SET foreign_key_checks = 0;'),
/* CREATE Member table */
knex.schema.createTable('Member', function (table) {
table.bigIncrements('id').primary().unsigned();
table.string('email',50);
table.string('password');
/* CREATE FKS */
table.bigInteger('ReferralId').unsigned().index();
table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id');
}),
/* CREATE Address table */
knex.schema.createTable('Address', function (table) {
table.bigIncrements('id').primary().unsigned();
table.index(['city','state','Zip']);
table.string('city',50).notNullable();
table.string('state',2).notNullable();
table.integer('Zip',5).unsigned().notNullable();
}),
knex.raw('SET foreign_key_checks = 1;')
]);
};
exports.down = function(knex, Promise) {
return Promise.all([
knex.raw('SET foreign_key_checks = 0;'),
knex.schema.dropTable('Address'),
knex.schema.dropTable('Member'),
knex.raw('SET foreign_key_checks = 1;')
]);
};
jedd.ahyoung est correct. Vous n'avez pas besoin de limiter votre pool de connexions à 1. Vous devez simplement chaîner vos promesses pour qu'elles ne soient pas exécutées en parallèle.
Par exemple:
exports.up = function(knex, Promise) {
return removeForeignKeyChecks()
.then(createMemberTable)
.then(createAddressTable)
.then(addForeignKeyChecks);
function removeForeignKeyChecks() {
return knex.raw('SET foreign_key_checks = 0;');
}
function addForeignKeyChecks() {
return knex.raw('SET foreign_key_checks = 1;');
}
function createMemberTable() {
return knex.schema.createTable('Member', function (table) {
table.bigIncrements('id').primary().unsigned();
table.string('email',50);
table.string('password');
/* CREATE FKS */
table.bigInteger('ReferralId').unsigned().index();
table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id');
});
}
function createAddressTable() {
return knex.schema.createTable('Address', function (table) {
table.bigIncrements('id').primary().unsigned();
table.index(['city','state','Zip']);
table.string('city',50).notNullable();
table.string('state',2).notNullable();
table.integer('Zip',5).unsigned().notNullable();
});
}
};
Il se peut également que quelque chose me manque, mais il semblerait que vous n’ayez pas besoin de supprimer puis de rétablir les contrôles de clé étrangère si vous créez la table d’adresses avant la table de membres.
Voici à quoi ressemblerait le code final:
exports.up = function(knex, Promise) {
return createAddressTable()
.then(createMemberTable);
function createMemberTable() {
return knex.schema.createTable('Member', function (table) {
table.bigIncrements('id').primary().unsigned();
table.string('email',50);
table.string('password');
/* CREATE FKS */
table.bigInteger('ReferralId').unsigned().index();
table.bigInteger('AddressId').unsigned().index().inTable('Address').references('id');
});
}
function createAddressTable() {
return knex.schema.createTable('Address', function (table) {
table.bigIncrements('id').primary().unsigned();
table.index(['city','state','Zip']);
table.string('city',50).notNullable();
table.string('state',2).notNullable();
table.integer('Zip',5).unsigned().notNullable();
});
}
};
Compris que cela ne fonctionnait pas à cause du regroupement des connexions. Il utiliserait une connexion différente pour exécuter chaque tâche de migration, ce qui empêcherait la définition correcte des contrôles de clé étrangère. réglage
pool:{
max:1
}
dans le fichier de configuration de la migration a résolu ce problème.
J'ai résolu ce problème en utilisant une transaction
transation.js
module.exports = function transaction(fn) {
return function _transaction(knex, Promise) {
return knex.transaction(function(trx) {
return trx
.raw('SET foreign_key_checks = 0;')
.then(function() {
return fn(trx, Promise);
})
.finally(function() {
return trx.raw('SET foreign_key_checks = 1;');
});
});
};
}
Fichier de migration
var transaction = require('../transaction');
function up(trx, Promise) {
return trx.schema
.createTable('contract', function(table) {
table.boolean('active').notNullable();
table.integer('defaultPriority').unsigned().references('priority.id');
table.integer('defaultIssueStatus').unsigned().references('issueStatus.id');
table.integer('owner').notNullable().unsigned().references('user.id');
})
.createTable('user', function (table) {
table.increments('id').primary();
table.datetime('createdAt');
table.datetime('updatedAt');
table.string('phoneNumber').notNullable().unique();
table.string('password').notNullable();
table.string('name').notNullable().unique();
table.string('email');
table.string('status');
table.string('roles').defaultTo('user');
table.integer('contract').unsigned().references('contract.id');
});
}
function down(trx, Promise) {
return trx.schema
.dropTable('contract')
.dropTable('user');
}
exports.up = transaction(up);
exports.down = transaction(down);
Je pensais que je mettrais à jour ceci, car il y a eu quelques ajouts à Javascript qui facilitent un peu cette tâche knex
nécessite toujours que vous retourniez un Promise
mais à l'intérieur de celui-ci Promise
, vous pouvez faire beaucoup de choses pour nettoyer le code lié à la création/modification de tables. Je préfère utiliser une combinaison de async
/await
et Promise.all
.
exports.up = function(knex, Promise) {
return new Promise(async (resolve, reject) => {
try {
await Promise.all([
knex.schema.createTable('videos', table => {
table.increments('id');
table.string('title');
table.string('director');
table.json('meta');
}),
knex.schema.createTable('books', table => {
table.increments('id');
table.string('title');
table.string('author');
table.json('meta');
})
]);
console.log('Tables created successfully');
resolve();
} catch(error) {
reject(error);
}
})
}
Si vous préférez créer chaque table individuellement, utilisez plutôt async
/await
.
exports.up = function(knex, Promise) {
return new Promise(async (resolve, reject) => {
try {
await knex.schema.createTable('videos', table => {
table.increments('id');
table.string('title');
table.string('director');
table.json('meta');
});
console.log('videos table created successfully!');
await knex.schema.createTable('books', table => {
table.increments('id');
table.string('title');
table.string('author');
table.json('meta');
});
console.log('books table created successfully!');
resolve();
} catch(error){
reject(error);
}
})
}
Cela garde les choses beaucoup plus propres, ne vous obligeant pas à enchaîner une série de then
s ou à les envelopper dans les fonctions environnantes. Il vous suffit await
pour chaque création de table de résoudre, puis de résoudre leur encapsulation, Promise
! Oui pour async
/await
!
Vous pouvez également suivre ce modèle pour la suppression de tables dans votre migration down
. Remplacez simplement les instructions knex.schema.createTable
par des instructions knex.schema.dropTable
.