Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comment puis-je utiliser un seul pool de connexions mssql sur plusieurs routes dans une application Web Express 4 ?

Cela fait 3 ans que j'ai posé et répondu à la question. Depuis lors, certaines choses ont changé. Voici la nouvelle solution basée sur ES6, mssql 4 et Express 4 que je vous propose aujourd'hui.

Deux éléments clés sont en jeu ici.

  1. Les modules sont mis en cache après leur premier chargement. Cela signifie que chaque appel à require('./db') renverra exactement le même objet. Le premier requis de db.js exécutera ce fichier, créera la promesse et l'exportera. La deuxième demande de db.js renverra CETTE même promesse sans exécuter le fichier. Et c'est cette promesse qui se résoudra avec la piscine.
  2. Une promesse peut être à nouveau confirmée. Et s'il s'est résolu avant, il se résoudra immédiatement avec ce qu'il a résolu la première fois, c'est-à-dire le pool.

Dans server.js

const express = require('express')
// require route handlers.
// they will all include the same connection pool
const set1Router = require('./routes/set1')
const set2Router = require('./routes/set2')

// generic express stuff
const app = express()

// ...
app.use('/set1', set1Router)
app.use('/set2', set2Router)

// No need to connect the pool
// Just start the web server

const server = app.listen(process.env.PORT || 3000, () => {
  const host = server.address().address
  const port = server.address().port

  console.log(`Example app listening at http://${host}:${port}`)
})

Dans db.js

const sql = require('mssql')
const config = {/*...*/}

const poolPromise = new sql.ConnectionPool(config)
  .connect()
  .then(pool => {
    console.log('Connected to MSSQL')
    return pool
  })
  .catch(err => console.log('Database Connection Failed! Bad Config: ', err))

module.exports = {
  sql, poolPromise
}

Dans routes/set1.js et routes/set2.js

const express = require('express')
const router = express.Router()
const { poolPromise } = require('./db')

router.get('/', async (req, res) => {
  try {
    const pool = await poolPromise
    const result = await pool.request()
        .input('input_parameter', sql.Int, req.query.input_parameter)
        .query('select * from mytable where id = @input_parameter')      

    res.json(result.recordset)
  } catch (err) {
    res.status(500)
    res.send(err.message)
  }
})

module.exports = router

Pour résumer

Vous obtiendrez toujours la même promesse en raison de la mise en cache du module et cette promesse sera, encore et encore, résolue avec le pool avec lequel elle a été résolue la première fois. Ainsi, chaque fichier de routeur utilise le même pool.

BTW :il existe des moyens plus simples d'effectuer l'essai de capture dans la voie express que je ne couvrirai pas dans cette réponse. Lisez à ce sujet ici :https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016

L'ancienne solution

C'est la solution que j'ai postée il y a 3 ans, car je croyais avoir une réponse qui valait la peine d'être partagée et je ne trouvais pas de solution documentée ailleurs. Ce sujet est également abordé dans quelques numéros (#118, #164, #165) de node-mssql.

Dans server.js

var express = require('express');
var sql     = require('mssql');
var config  = {/*...*/};
//instantiate a connection pool
var cp      = new sql.Connection(config); //cp = connection pool
//require route handlers and use the same connection pool everywhere
var set1    = require('./routes/set1')(cp);
var set2    = require('./routes/set2')(cp);

//generic express stuff
var app = express();

//...
app.get('/path1', set1.get);
app.get('/path2', set2.get);

//connect the pool and start the web server when done
cp.connect().then(function() {
  console.log('Connection pool open for duty');

  var server = app.listen(3000, function () {

    var host = server.address().address;
    var 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);
});

Dans routes/set1.js

var sql     = require('mssql');

module.exports = function(cp) {
  var me = {
    get: function(req, res, next) {
      var request = new sql.Request(cp);
      request.query('select * from test', function(err, recordset) {
        if (err) {
          console.error(err);
          res.status(500).send(err.message);
          return;
        }
        res.status(200).json(recordset);
      });
    }
  };

  return me;
};