I'm have a bad experience using mssql package which is return the connection as a promise so to be able to use a method like query
I should to first wait for connection then use it something like
const sql = require('mssql')
const sqlConfig = {
user: process.env.DB_USER,
password: process.env.DB_PWD,
database: process.env.DB_NAME,
server: 'localhost',
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt: true, // for azure
trustServerCertificate: false // change to true for local dev / self-signed certs
}
}
sql.connect(config).then(async pool => {
const query = await pool.query`select * from table_name`;
console.log(query)
})
But certainly I won't use that connection in a single file I want to export it to use it in a different routes files so for that case I found 2 solutions who isn't the best practice or not a good programming experience in my opinion first is introduced in the package docs which is connect to the SQL server first then run your node server and attach the connection in the app locals and I think it's really so bad solution it's stopping the whole server on the database connection what if the connection failed that's means that the whole server won't start even if there's a static files that doesn't require a database connection the user won't be able to access it anymore here's the solution provided
const express = require('express')
const sql = require('mssql')
const config = {/*...*/}
//instantiate a connection pool
const appPool = new sql.ConnectionPool(config)
//require route handlers and use the same connection pool everywhere
const route1 = require('./routes/route1')
const app = express()
app.get('/path', route1)
//connect the pool and start the web server when done
appPool.connect().then(function(pool) {
app.locals.db = pool;
const server = app.listen(3000, function () {
const host = server.address().address
const port = server.address().port
console.log('Example app listening at http://%s:%s', host, port)
})
}).catch(function(err) {
console.error('Error creating connection pool', err)
});
So to access it I will use something like the following
const express = require('express');
const router = express.Router();
router.get('/', async (req, res, next) => {
req.app.locals.db.query('SELECT TOP 10 * FROM table_name', function(err, recordset) {
if (err) {
console.error(err)
res.status(500).send('SERVER ERROR')
return
}
res.status(200).json({ message: 'success' })
})
})
That was the first solution and the second solution that I found is exporting the connection and in each time I want to use something like query
method I can't call it directly I should to repeat a static step who is const pool = await connection; const query = await connection.query('my query string')
in fact that solution is better than the first but there's a step I should to repeat it in each time I think that this isn't a good programmer experience here's the code example
const sql = require('mssql');
const { normalizePort } = require('./handlers');
const {
SQL_SERVER_USER,
SQL_SERVER_PASSWORD,
SQL_SERVER,
SQL_SERVER_DATABASE,
SQL_SERVER_PORT
} = require('./configurations/appConfig');
const config = {
user: SQL_SERVER_USER,
password: SQL_SERVER_PASSWORD,
database: SQL_SERVER_DATABASE,
server: SQL_SERVER,
port: normalizePort(SQL_SERVER_PORT),
pool: {
max: 10,
min: 0,
idleTimeoutMillis: 30000
},
options: {
encrypt: true,
trustServerCertificate: true, // change to true for local dev / self-signed certs
}
}
const connection = sql.connect(sqlConfig)
module.exports = connection;
Let's assume that the filename of the code above is db.js
and then in a route file which is called production.js
there's 3 routes so let's import the connection above and use it in that route
const express = require('express');
const router = express.Router();
const connection = require('../db.js')
router.get('/products', async (req, res, next) => {
const pool = await connection;
const query = await pool.query`select * from products`;
res.setHeader("Content-Type", 'application/json; charset=utf-8');
res.status(200).send(JSON.stringify(query, null, 4));
});
router.post('/brands', async (req, res, next) => {
const pool = await connection;
const query = await pool.query`select * from brands`;
res.setHeader("Content-Type", 'application/json; charset=utf-8');
res.status(200).send(JSON.stringify(query, null, 4));
});
router.post('/categories', async (req, res, next) => {
const pool = await connection;
const query = await pool.query`select * from categories`;
res.setHeader("Content-Type", 'application/json; charset=utf-8');
res.status(200).send(JSON.stringify(query, null, 4));
});
module.exports = router
In the example above in each route I should to call const pool = await connection;
that repetitive code I think it's not the best practice and not a good programmer experience I'm looking for a better solution where I can import the connection and directly access the query
method without extra steps.