如何在Express 4 Web应用程序中的多个path中使用单个mssql连接池?

我想在Node JS Express 4 Web应用程序中使用node-mssql作为MSSQL数据库连接器。 路由处理程序逻辑在单独的文件中处理。

如何创build单个/全局连接池,并在处理路由逻辑的多个文件中使用它? 我不想在每个路由处理函数/文件中创build一个新的连接池。

我实际上是问自己回答这个问题,因为我相信我有一个值得分享的答案,而且我在其他地方找不到有文档的解答。 另外在node-mssql的一些问题( #118 , #164 , #165 )中讨论了这个话题。

这是我的解决scheme:

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

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

当您configuration您的应用程序(如创build快速服务器时),build立数据库连接。 确保这是完成之前,你需要所有的路线! (finagle在文件顶部的要求)

就像文档:

var sql = require('mssql'); var connection = new sql.Connection(..... //store the connection sql.globalConnection = connection;

然后在你所有的路由文件中,你可以这样做:

var sql = require('mssql'); var sqlConn = sql.globalConnection; var request = new sql.Request(sqlConn); //...

这应该做到这一点!

所有这一切,使用knex来pipe理你的MySQL查询build设。 它有一个内置的连接池,并以相同的方式存储连接的knex实例。 以及慷慨的帮助真棒。

src/config.js

 export default { database: { server: process.env.DATABASE_SERVER || '<server>.database.windows.net', port: 1433, user: process.env.DATABASE_USER || '<user>@<server>', password: process.env.DATABASE_PASSWORD || '<password>', database: process.env.DATABASE_NAME || '<database>', connectionTimeout: 30000, driver: 'tedious', stream: false, options: { appName: '<app-name>', encrypt: true } } }; 

src/server.js

 import sql from 'mssql'; import express from 'express'; import config from './config'; // Create and configure an HTTP server const server = express(); server.set('port', (process.env.PORT || 5000)); // Register Express routes / middleware server.use('/api/user', require('./api/user'); // Open a SQL Database connection and put it into the global // connection pool, then launch the HTTP server sql.connect(config.database, err => { if (err) { console.log('Failed to open a SQL Database connection.', err.stack); } server.listen(server.get('port'), () => { console.log('Node app is running at http://127.0.0.1:' + server.get('port')); }); }); sql.on('error', err => console.log(err.stack)); 

src/api/user.js

 import sql from 'mssql'; import { Router } from 'express'; const router = new Router(); router.get('/:id', async (req, res, next) => { try { const request = new sql.Request(); request.input('UserID', req.params.id); request.multiple = true; const dataset = await request.query(` SELECT UserID, Name, Email FROM [User] WHERE UserID = @UserID; SELECT r.RoleName FROM UserRole AS r INNER JOIN [User] AS u ON u.UserID = r.UserID WHERE u.UserID = @UserID `); const user = dataset[0].map(row => ({ id: row.UserID, name: row.Name, email: row.Email, roles: dataset[1].map(role => role.RoleName) })).shift(); if (user) { res.send(user); } else { res.statusCode(404); } } catch (err) { next(err); } }); export default router; 

另请参阅 适用于Node.js的MSSQL SDK , T-SQL参考 , React入门工具包

我使用了类似的概念( single connection pool ),但将连接逻辑封装在一个文件中(不需要将连接池传递到其他地方)。 下面的connPoolPromise只会初始化一次,因为模块在第一次被加载后被caching。

例如DBUtil.js

 var sql = require('mssql'), connPoolPromise = null; function getConnPoolPromise() { if (connPoolPromise) return connPoolPromise; connPoolPromise = new Promise(function (resolve, reject) { var conn = new sql.Connection(require('./dbConfig')); conn.on('close', function () { connPoolPromise = null; }); conn.connect().then(function (connPool) { return resolve(connPool); }).catch(function (err) { connPoolPromise = null; return reject(err); }); }); return connPoolPromise; } // Fetch data example exports.query = function(sqlQuery, callback) { getConnPoolPromise().then(function (connPool) { var sqlRequest = new sql.Request(connPool); return sqlRequest.query(sqlQuery); }).then(function (result) { callback(null, result); }).catch(function (err) { callback(err); }); }; 

用法user.js

 var DBUtil = require('./DBUtil'); DBUtil.query('select * from user where userId = 12', function (err, recordsets) { if (err) return callback(err); // Handle recordsets logic }