Я использую Sequelize для подключения к базе данных Microsoft Azure SQL. Я могу успешно подключиться к нему, но когда я пытаюсь отправить свои файлы миграции, он выдает эту ошибку, когда я пытаюсь установить ассоциации.
Sequelize CLI [Node: 10.15.3, CLI: 5.5.1, ORM: 5.19.2]
Loaded configuration file "config\config.json".
Using environment "development".
(node:16208) [SEQUELIZE0004] DeprecationWarning: A boolean value was passed to options.operatorsAliases. This is a no-op with v5 and should be removed.
== 20191003000554-create-user: migrating =======
== 20191003000554-create-user: migrated (0.141s)
== 20191003012530-create-workshop: migrating =======
== 20191003012530-create-workshop: migrated (0.131s)
== 20191003012716-create-location: migrating =======
== 20191003012716-create-location: migrated (0.219s)
== 20191003012841-create-instructor: migrating =======
== 20191003012841-create-instructor: migrated (0.163s)
== 20191003013038-create-notification: migrating =======
== 20191003013038-create-notification: migrated (0.162s)
== 20191022001209-create-class: migrating =======
== 20191022001209-create-class: migrated (0.135s)
== 20191022001540-add-associations: migrating =======
ERROR: SequelizeDatabaseError: Could not create constraint or index. See previous errors.
at Query.formatError (C:\Users\Ryan\Desktop\sddec19-04\node_modules\sequelize\lib\dialects\mssql\query.js:314:12)
at Request.connection.lib.Request [as userCallback] (C:\Users\Ryan\Desktop\sddec19-04\node_modules\sequelize\lib\dialects\mssql\query.js:74:23)
at Request.callback (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\request.js:37:27)
at Connection.endOfMessageMarkerReceived (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\connection.js:2104:20)
at Connection.dispatchEvent (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\connection.js:1084:36)
at Parser.tokenStreamParser.on (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\connection.js:914:14)
at Parser.emit (events.js:189:13)
at Parser.parser.on.token (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\token\token-stream-parser.js:27:14)
at Parser.emit (events.js:189:13)
at addChunk (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_readable.js:297:12)
at readableAddChunk (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_readable.js:279:11)
at Parser.Readable.push (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_readable.js:240:10)
at Parser.Transform.push (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_transform.js:139:32)
at Parser.afterTransform (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_transform.js:88:10)
at Parser._transform (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\token\stream-parser.js:41:7)
at Parser.Transform._read (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_transform.js:177:10)
at Parser.Transform._write (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_transform.js:164:83)
at doWrite (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_writable.js:405:139)
at writeOrBuffer (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_writable.js:394:5)
at Parser.Writable.write (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\node_modules\readable-stream\lib\_stream_writable.js:303:11)
at Parser.addEndOfMessageMarker (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\token\token-stream-parser.js:45:24)
at Connection.message (C:\Users\Ryan\Desktop\sddec19-04\node_modules\tedious\lib\connection.js:2093:32)
Я рассмотрел некоторые другие вопросы здесь, ноНи одно из них не имеет прямого отношения к тому, что я вижу.
Я использую sequelize-cli для отправки миграций, моделей и т. д. в базу данных.
Вот моя модель длятаблица Users
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
Role: DataTypes.STRING,
FirstName: DataTypes.STRING,
LastName: DataTypes.STRING,
Email: DataTypes.STRING,
Password: DataTypes.STRING,
EmployedDate: DataTypes.STRING
}, {});
User.associate = function(models) {
User.hasMany(models.Instructor, as: 'ManagerId');
User.hasMany(models.Notification, as: 'UserId');
User.hasMany(models.Workshop, as: 'CreatorId');
User.hasMany(models.Notification, as: 'RequesterId');
};
return User;
};
Вот моя модель для таблицы Instructors
'use strict';
module.exports = (sequelize, DataTypes) => {
const Instructor = sequelize.define('Instructor', {
CertificationLevel: DataTypes.STRING,
CPRCertificationDate: DataTypes.DATE,
StrengthTrainingLevel: DataTypes.STRING,
KettelbellLevel: DataTypes.STRING,
ClassesTaught: DataTypes.INTEGER,
UserId: DataTypes.INTEGER,
ManagerId: DataTypes.INTEGER,
MostRecentWorkshopId: DataTypes.INTEGER,
}, {});
Instructor.associate = function(models) {
Instructor.belongsTo(models.User, as: 'UserId');
Instructor.hasMany(models.Workshop, as: 'InstructorId');
Instructor.belongsTo(models.Workshop, as: 'MostRecentWorkshopId');
Instructor.hasMany(models.Class, as: 'InstructorId');
};
return Instructor;
};
Вот моя модель для таблицы Locations
'use strict';
module.exports = (sequelize, DataTypes) => {
const Location = sequelize.define('Location', {
LocationName: DataTypes.STRING,
Address: DataTypes.STRING,
City: DataTypes.STRING,
State: DataTypes.STRING,
ZipCode: DataTypes.INTEGER,
Region: DataTypes.STRING,
Latitude: DataTypes.FLOAT,
Longitude: DataTypes.FLOAT,
PhoneNumber: DataTypes.STRING,
MainContact: DataTypes.STRING,
Owners: DataTypes.STRING,
Email: DataTypes.STRING
}, {});
Location.associate = function(models) {
Location.hasMany(models.Workshop, as: 'LocationId');
};
return Location;
};
Есть и другие модели, но у них нет ассоциаций, определенных в их файле модели, поэтому я исключил их.
Вот моя миграция, которая выполняет все ассоциации. Он запускается последним из всех файлов миграции.
module.exports = {
up: (queryInterface, Sequelize) => {
// Instructor belongsTo User (itself)
return queryInterface.addColumn(
'Instructors', // Name of the Source model
'UserId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Users', // Name of the Target model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
).then(() => {
// Manager (User) hasMany Instructors below them
return queryInterface.addColumn(
'Instructors', // Name of the Target model
'ManagerId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Users', // Name of the Source model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// User hasMany Notifications
return queryInterface.addColumn(
'Notifications', // Name of the Target model
'UserId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Users', // Name of the Source model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// User hasMany Workshops that they might have created
return queryInterface.addColumn(
'Workshops', // Name of the Target model
'CreatorId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Users', // Name of the Source model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// Instructor hasMany Workshops that they might lead
return queryInterface.addColumn(
'Workshops', // Name of the Target model
'InstructorId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Instructors', // Name of the Source model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// Location hasMany Workshops that can be located there
return queryInterface.addColumn(
'Workshops', // Name of the Target model
'LocationId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Locations', // Name of the Source model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// Instructor belongsTo their most recent workshop
return queryInterface.addColumn(
'Instructors', // Name of the Source model
'MostRecentWorkshopId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Workshops', // Name of the Target model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// User hasMany Notifiactions that are related to them
return queryInterface.addColumn(
'Notifications', // Name of the Target model
'RequesterId', // Name of the key we are adding
{
type: Sequelize.INTEGER,
references: {
model: 'Users', // Name of the Source model
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
}).then(() => {
// Instructor hasMany Classes that they might have taught
return queryInterface.addColumn(
'Classes',
'InstructorId',
{
type: Sequelize.INTEGER,
references: {
model: 'Instructors',
key: 'id',
},
onUpdate: 'CASCADE',
onDelete: 'SET NULL',
}
);
});
},
down: (queryInterface, Sequelize) => {
// Remove UserId column
return queryInterface.removeColumn(
'Instructors', // Name of Source model
'UserId' // Name of column to delete
).then(() => {
// Remove ManagerId column
return queryInterface.removeColumn(
'Instructors', // Name of Target model
'ManagerId' // Name of column to delete
);
}).then(() => {
// Remove UserId column
return queryInterface.removeColumn(
'Notifications',
'UserId'
);
}).then(() => {
// Remove CreatorId column
return queryInterface.removeColumn(
'Workshops',
'CreatorId'
);
}).then(() => {
// Remove InstructorId column
return queryInterface.removeColumn(
'Workshops',
'InstructorId'
);
}).then(() => {
// Remove LocationId column
return queryInterface.removeColumn(
'Workshops',
'LocationId'
);
}).then(() => {
// Remove MostRecentWorkshopId column
return queryInterface.removeColumn(
'Instructors',
'MostRecentWorkshopId'
);
}).then(() => {
// Remove RequesterId column
return queryInterface.removeColumn(
'Notifications',
'RequesterId'
);
}).then(() => {
// Remove InstructorId column
return queryInterface.removeColumn(
'Classes',
'InstructorId'
);
});
}
};
Кажется, что происходит, когда определяется первая связь между Инструкторами и Пользователями, но затем появляется ошибка, когда запускается следующая связь.
Этот файл работал нормально, когда я запускал его в своей локальной базе данных MySQL. Может ли быть так, что SQL Server не разрешает эти множественные ассоциации / циклические ассоциации? Например, потому что два разных столбца в таблице «Инструкторы» имеют ссылки на «id» в Users?
Нужно ли вообще столько ассоциаций?
Миграции успешно работают, когда я удаляю ассоциации, смотрящие на одни и те же столбцы, а также удаляю циклические ассоциации, но я чувствую, что что-то упустилэто могло бы сделать все это гладким.