Nodejs MSSQL how to pool multiple databases simultaneously - node.js

I am building a massive intranet using NodeJS, converting from ASP.Net C#. I keep running into database errors about cannot use the connection while it is closing or connection must be opened etc. I am attempting to convert over to connection pooling but am running into issues with it since I am connecting with (currently) 6 different databases, and being new to Node MSSQL I am kind of at a loss for how to proceed.
Originally I was making a call to "runqueries()" passing in the config data, and from there opening a connection to the desired database. The connection details were stored in a JSON object in the database.js file. I am now trying to create the pool in the database.js file and return that as an object to connect.
//database.js
const sql = require('mssql');
// const Config = {
// MCAIntranet: {
// user: 'username',
// password: 'password',
// server: 'mcasql',
// database: 'MCAIntranet',
// options: { enableArithAbort: true }
// },
// DEV_Intranet: {
// server: 'mcasql',
// user: 'username',
// password: 'password',
// database: 'DEV_Intranet_Test',
// options: { enableArithAbort: true }
// },
// CMR: {
// user: 'username',
// password: 'password',
// server: 'mcasql',
// database: 'Corporate_Morning_Reports',
// options: { enableArithAbort: true }
// },
// Lansa: {
// user: 'username',
// password: 'password',
// server: 'mcasql',
// database: 'LANSA',
// options: { enableArithAbort: true }
// },
// Roles: {
// user: 'username',
// password: 'password',
// server: 'mcasql',
// database: 'dotNetRolesDB_New',
// options: { enableArithAbort: true }
// },
// PreAuth:{
// user: 'username',
// password: 'password',
// server: 'mcasql',
// database: 'PreAuth',
// options: { enableArithAbort: true }
// }
// }
const CORPIntranet = () => {
new sql.ConnectionPool({
user: 'username',
password: 'password',
server: 'dbserver',
database: 'CORPIntranet',
options: { enableArithAbort: true }
})
.connect().then(pool => pool)
};
const DEV_Intranet = () => {
new sql.ConnectionPool({
user: 'username',
password: 'password',
server: 'dbserver',
database: 'CORPIntranet_Test',
options: { enableArithAbort: true }
})
.connect().then(pool => pool)
};
const CMR = () => {
new sql.ConnectionPool({
user: 'username',
password: 'password',
server: 'dbserver',
database: 'Corporate_Morning_Reports',
options: { enableArithAbort: true }
})
.connect().then(pool => pool)
};
const Lansa = () => {
new sql.ConnectionPool({
user: 'username',
password: 'password',
server: 'dbserver',
database: 'LANSA',
options: { enableArithAbort: true }
})
.connect().then(pool => pool)
};
const Roles = () => {
new sql.ConnectionPool({
user: 'username',
password: 'password',
server: 'dbserver',
database: 'dotNetRolesDB_New',
options: { enableArithAbort: true }
})
.connect().then(pool => pool)
};
const PreAuth = () => {
new sql.ConnectionPool({
user: 'username',
password: 'password',
server: 'dbserver',
database: 'PreAuth',
options: { enableArithAbort: true }
})
.connect().then(pool => pool)
};
const Config = {
CORPIntranet: CORPIntranet(),
DEV_Intranet: DEV_Intranet(),
CMR: CMR(),
Lansa: Lansa(),
Roles: Roles(),
PreAuth: PreAuth()
}
module.exports = Config;
I am calling this using the code await dataQuery.runQuery(query, config.PreAuth);
and the runquery() code is
//dataQueries.js
let sql = require('mssql');
const runQuery = async (query, database) => {
try {
// await sql.connect(database);
// let request = new sql.Request();
let recordset = await database.query(query);
return recordset;
} catch (ex) {
console.log(ex);
{ error: "dataQueries.js 17" + ex.Message };
return "False";
}
finally{
sql.close();
}
}
I know that I don't need the "sql.close()" at the end but I am in the process of conversion. I am now getting a typeError: database.query is not a function.
If you could point out where my fault lies in this, and better yet link a good tutorial that assumes neophyte status of the reader, that would be excellent.
Thanks in advance.
EDIT
In my runQuery() function I changed the code to
let pool=await database();
let recordset = await pool.query(query);
which now allows the query to run. But is this the correct method and will it prevent errors on multiple database connections?

I solved this problem in the simplest fashion possible. I switched from using the mssql module to sequelize.js which gives a level of abstraction from the database access and connectivity, and simplifies access to multiple databases along with database types (MSSQL, Postgres, MongoDB etc)

Related

makes a database connection in the constructor using Knex

I am trying to implement knex connection below into an equivalent DB class. I searched but did not find any example implementation.
var knex = require('knex')({
client: 'pg',
connection: {
host: '127.0.0.1',
user: 'your_database_user',
password: 'your_database_password',
database: 'myapp_test'
},
pool: { min: 0, max: 7 }
})
let knex = require("knex");
class Database {
constructor(connection) {
this.connection = connection;
}
connect(option = {}) {
this.instance = knex(Object.assign(this.connection, option));
}
}
let db = new Database({
connection: {
host: '127.0.0.1',
user: 'your_database_user',
password: 'your_database_password',
database: 'myapp_test'
}
});
db.connect({
pool: { min: 0, max: 7 },
client: 'pg'
});

Is there anyway to return response to client when mongodb is stopped in nodejs http requests?

I have an express app and using Mongodb. Here is my 2 connections with database :
const mongoose = require("mongoose");
try {
const db1 = mongoose.createConnection(
`mongodb://${process.env.DB_DOMAIN}/${process.env.DB_1_NAME}`,
{
authSource: "admin",
user: process.env.DB_USERNAME,
pass: process.env.DB_PASSWORD,
useNewUrlParser: true,
tls: true,
sslValidate: false,
connectTimeoutMS: process.env.DB_TIMEOUT, // 15000
}
);
const db2 = mongoose.createConnection(
`mongodb://${process.env.DB_DOMAIN}/${process.env.DB_2_NAME}`,
{
authSource: "admin",
user: process.env.DB_USERNAME,
pass: process.env.DB_PASSWORD,
useNewUrlParser: true,
tls: true,
sslValidate: false,
connectTimeoutMS: process.env.DB_TIMEOUT, // 15000
}
);
module.exports = {
db1,
db2,
};
} catch (err) {
console.log(err);
}
The Mongodb service is stopped. When I request to do something, it takes long time and doesn't return any error. How can I handle it?

Problem with connect by Sequelize when I connect to SQL Server

I use the mssql package and connect to database like this:
const sql = require('mssql')
const config = {
user: 'sa',
password: 'xxxxxx',
server: 'xxx.xxx.xxx.xxx',
database: 'zorgo',
options : {
enableArithAbort: false,
cryptoCredentialsDetails: {
minVersion: 'TLSv1'
}
}
};
Now I want to try 'sequelize' library and try to connect
const sequelize = new Sequelize('zorgo', 'sa', 'xxxxxx', {
dialect: 'mssql',
host: 'xxx.xxx.xxx.xxx',
options: {
enableArithAbort: false,
cryptoCredentialsDetails: {
minVersion: 'TLSv1'
}
}
});
But I get an error
Failed to connect to xxx.xxx.xxx.xxx:1433 - 584:error:1425F102:SSL routines:ssl_choose_client_version:unsupported protocol
Please help me resolve this problem
I found the answer to my question
const sequelize = new Sequelize('zorgo', 'sa', 'xxxxxx', {
dialect: 'mssql',
host: 'xxx.xxx.xxx.xxx',
dialectOptions: {
options: {
enableArithAbort: false,
cryptoCredentialsDetails: {
minVersion: 'TLSv1'
}
}
}
});
And works well...

Certificate error when connecting to SQL Server

When trying to connect to SQL Server, I get the following error:
(node:9364) UnhandledPromiseRejectionWarning: ConnectionError: Failed to connect to 10.120.6.11:1433 - self signed certificate
When I use SQL Server 2014, it works normally.
Note: You need a vpn to connect.
Code:
const config = {
port: parseInt(process.env.DB_PORT, 10),
server: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_Database,
stream: false,
options: {
trustedConnection: true,
encrypt: true,
enableArithAbort: true,
trustServerCertificate: false,
},
}
sql.connect(config).then(pool => {
if (pool.connecting) {
console.log('Connecting to the database...')
}
if (pool.connected) {
console.log('Connected to SQL Server')
}
})
I had the same error message (Failed to connect to xxx:1433 - self signed certificate). Then I used trustServerCertificate: true. This fixed the error for me.
I encountered the same problem on my project. I manage to solve the problem by adding trustServerCertificate: true
Example (NestJS and TypeORM usage):
TypeOrmModule.forRoot({
type: 'mssql',
host: 'localhost\\SQLEXPRESS',
username: 'sa',
password: 'root',
database: 'DB',
entities: [__dirname + '/**/*.entity{.ts,.js}'],
synchronize: true,
extra: {
trustServerCertificate: true,
}
}),
What works with me, with the full script:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'sa',
password: 'P#ssw0rd',
server: 'WIN-N4J1057LVFV',
database: 'WIN-PAK_ALL',
synchronize: true,
trustServerCertificate: true,
};
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query('select * from cardHistory', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});
If you're using a connection string:
sql.connect('Server=localhost,1433;Database=database;User Id=username;Password=password;Trusted_Connection=True;TrustServerCertificate=True;');

waterline and mysql without sails

I am building a node app and want to use waterline and mysql without sails. I cannot get the adapter to work. The exact error I get with the code from below is:
C:\node\mlb\node_modules\waterline\lib\waterline\core\index.js:70
var schemaAttributes = this.waterline.schema[this.identity].attributes;
TypeError: Cannot read property 'undefined' of undefined
Here is my code:
var Waterline = require('waterline');
var mysql = require('sails-mysql');
mysql.config = {
host: 'localhost',
database: 'mlb',
port: '3306',
username: 'admin',
password: 'xxxxxxxx'
}
var Batter = Waterline.Collection.extend({
adapter: 'mysql',
attributes: {
name: {
type: 'string',
required: true
}
}
});
new Batter({ tableName: 'batters', adapters: { mysql: mysql }}, function (err, Model) {
Model.findAll().exec(function(err, batters) {
// Now we have an array of users
});
});

Resources