Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Wie kann ich einen einzelnen mssql-Verbindungspool über mehrere Routen in einer Express 4-Webanwendung verwenden?

Es ist 3 Jahre her, dass ich die Frage gestellt und beantwortet habe. Seitdem hat sich einiges geändert. Hier ist die neue Lösung basierend auf ES6, mssql 4 und Express 4, die ich heute vorschlagen würde.

Hier spielen zwei Schlüsselelemente eine Rolle.

  1. Module werden nach dem ersten Laden zwischengespeichert. Das bedeutet, dass jeder Aufruf von require('./db') genau dasselbe Objekt zurückgibt. Die erste Anforderung von db.js führt diese Datei aus, erstellt das Promise und exportiert es. Die zweite Anforderung von db.js gibt DAS gleiche Versprechen zurück, ohne die Datei auszuführen. Und es ist dieses Versprechen, das mit dem Pool eingelöst wird.
  2. Ein Versprechen kann erneut bestätigt werden. Und wenn es vorher aufgelöst wurde, wird es sofort wieder mit dem aufgelöst, was beim ersten Mal aufgelöst wurde, nämlich dem Pool.

In 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}`)
})

In 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
}

In routes/set1.js und 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

Zusammenfassend

Aufgrund des Modul-Cachings erhalten Sie immer das gleiche Versprechen, und dieses Versprechen wird immer wieder mit dem Pool aufgelöst, mit dem es beim ersten Mal aufgelöst wurde. Somit verwendet jede Router-Datei denselben Pool.

Übrigens:Es gibt einfachere Möglichkeiten, den Versuchsfang auf der Expressroute zu umgehen, die ich in dieser Antwort nicht behandeln werde. Lesen Sie hier darüber:https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016

Die alte Lösung

Dies ist die Lösung, die ich vor 3 Jahren gepostet habe, weil ich glaubte, eine Antwort zu haben, die es wert ist, geteilt zu werden, und ich nirgendwo anders eine dokumentierte Lösung finden konnte. Auch in einigen Ausgaben (#118, #164, #165) bei node-mssql wird dieses Thema behandelt.

In 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);
});

In 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;
};