2016-10-21 2 views
0
var state = require('./state') 
module.exports = function (sequelize, DataTypes) { 
    var city = sequelize.define('city', { 
     city_id : { 
      type : DataTypes.INTEGER, 
      autoIncrement : true, 
      primaryKey : true 
     }, 
     city_name : { 
      type : DataTypes.STRING, 
      allowNull : false, 
      unique : true 
     }, 
     city_state_id : { 
      type : DataTypes.INTEGER, 
      allowNull : false, 
      references : { 
       model : 'states', 
       key : 'state_id' 
      } 
     } 
    } 
    return city; 
} 

Это мой файл ссылок.Unhandled Rejection SequelizeDatabaseError: ошибка ограничения внешнего ключа: не может добавить внешний ключ

module.exports = function (sequelize, DataTypes) { 
    var state = sequelize.define('state', { 
     state_id: { 
      type: DataTypes.INTEGER, 
      autoIncrement: true, 
      primaryKey: true 
     }, 
     state_name: { 
      type: DataTypes.STRING, 
      allowNull: false, 
      unique: true 
     }, 
    }) 
    return state; 
} 

Я не знаю, почему я не могу добавить ограничение внешнего ключа здесь. Кто-нибудь может мне помочь? Я получаю сообщение об ошибке, как это:

Unhandled отказ SequelizeDatabaseError: ER_CANNOT_ADD_FOREIGN: Невозможно добавить ограничение внешнего ключа Когда я пытаюсь выполнить migration.js на терминал: узел migration.js

migration.js:

/*jslint node: true */ 
'use strict'; 
var Sequelize = require('sequelize'); 
var fs = require('fs'); 
var schema_dir = './schema/'; 
var config = require('./config').mysql_conf; 
var connection = new Sequelize(config.database, config.username, config.password, config); 
fs.readdir(schema_dir, function(err, files) { 
    if (err) { 
     console.log(err); 
    } else { 
     files = files.sort(); 
     console.log(files); 
     for (var i = 0; i < files.length; i++) { 
      var module_name = files[i].slice(0, -3); 
      console.log(schema_dir + files[i]); 
      // var schema = require(schema_dir + module_name); 
      try { 
       var model = connection['import']('' + schema_dir + module_name); 
       model.sync().then(function() { 
        console.log("table created: " + module_name); 
       }); 
       model.sync({force : true}) 
      } catch (ex) { 
       console.log("error with module_name: " + module_name, ex); 
      } 
     } 
    } 

}); 

У кого-нибудь есть идея, почему это происходит?

ответ

3

Несколько вещей, которые необходимо понимать/исправлять, чтобы убедиться, что это работает правильно.

синхронизации() против синхронизации ({силы: истинно})

sync() будет работать, тогда как CREATE TABLE IF NOT EXISTSsync({force: true}) будет работать DROP TABLE IF EXISTS, а затем создает таблицу снова. Таким образом, этот способ миграции будет не работать в средах, расположенных выше локальных/dev. Кроме того, если вы хотите создать столбец, измените тип данных и т. Д., Вы не используете , применяя эти методы для внесения изменений.

Используйте это, чтобы протестировать локально, а затем создайте файл миграции через SHOW CREATE TABLE и запустите их через Sequelize migration.

Асинхронная природа синхронизации

sync() это ни парадоксально, что означает асинхронный синхронный цикл не гарантирует, что каждая модель загружается в порядке. Это может выводить различные журналы ошибок и выкидывать вас. Вы должны использовать асинхронные модули обработки, как в асинхронном:

async.eachSeries(files, function(file, callback) { 
    var model = require(currentDir + '/' + file); 
    model 
     .sync({force: true}) 
     .then(function() { 
      console.log('Force-synced %s', file); 
      callback(); 
     }) 
     .catch(callback); 
}, function(err) { 
    if(err) throw err; 
    console.log('Completed migration in order as such %o', files); 
}); 

Порядок миграции файлов

У вас есть имена файлов, как city.model.js и state.model.js. Так fs.readdir будет читать их в алфавитном порядке,

city_state_id : { 
     type : DataTypes.INTEGER, 
     allowNull : false, 
     references : { 
      model : 'states', 
      key : 'state_id' 
     } 
    } 

не может ссылаться на таблицу states, так как он еще не существует.

Вам необходимо будет заказать их должным образом. Один из способов заключается в создании массива заказа, как это:

var order = [ 
    'state', 
    'city' 
]; 

async.eachSeries(order, function(file, callback) { 
    var model = require(currentDir + '/' + file + '.model.js'); 
    model 
     .sync({force: true}) 
     .then(function() { 
      console.log('Force-synced %s', file); 
      callback(); 
     }) 
     .catch(callback); 
}, function(err) { 
    if(err) throw err; 
    console.log('Completed migration in order as such %o', files); 
}); 

Другие не будет ждать модели для загрузки

Если вы тестируете или сервер, они могут начать пытаться получить доступ к модели, прежде чем они загружены. Асинхронный характер sync не позволяет серверу ждать загрузки моделей.

Решение заключается в использовании моделей в качестве способа запроса, а не в способе изменения структуры таблицы.Это необходимо использовать для локального тестирования и для внесения изменений использовать Sequelize migration.