我在 Node.js express 应用程序中使用mssql跨许多不同的 SQL 服务器连接到许多不同的数据库。
我构建了以下示例来演示我的代码的一般结构:
app.get('/api/example'), async (request, response) => {
// FYI I may be using await incorrect here since I'm new to it, just using it here for code simplicity
let results1 = await GetDataFromSqlServerA()
let results2 = await GetDataFromSqlServerB()
response.status(200).send([results1, results2])
});
function GetDataFromSqlServerA() {
return new Promise(function(resolve, reject) {
let sql = require("mssql")
let sqlConnectionDetails = {
user: 'test',
password: 'foobar',
server: 'SQLServerA',
database: 'DatabaseA'
}
sql.connect(sqlConnectionDetails, function (error) {
let sqlRequest = new sql.Request()
let queryText = 'SELECT * FROM TableA'
sqlRequest.query(queryText, function (error, results) {
sql.close()
resolve(results)
})
})
})
}
function GetDataFromSqlServerB() {
return new Promise(function(resolve, reject) {
let sql = require("mssql")
let sqlConnectionDetails = {
user: 'test',
password: 'foobar',
server: 'SQLServerB',
database: 'DatabaseB'
}
sql.connect(sqlConnectionDetails, function (error) {
let sqlRequest = new sql.Request()
let queryText = 'SELECT * FROM TableB'
sqlRequest.query(queryText, function (error, results) {
sql.close()
resolve(results)
})
})
})
}
我有一个请求,它从两个单独的 SQL 服务器位置异步查找数据。要进行的第一个 SQL 调用执行正常,但第二个失败Invalid object 'Table2'
。它无法找到该表,因为出于某种原因,第二个调用获取了第一个调用的连接详细信息。它指向错误的 SQL 服务器和数据库!
我会认为这是不可能的,因为这些功能在它们自己的范围内。第一个 SQL 调用应该对第二个 SQL 调用一无所知,反之亦然 - 或者至少我会这么想。
我也尝试过在全局定义一个sql实例,但发生了同样的问题。
我可以有一个函数与服务器 A 建立 SQL 连接,向服务器 A 发出请求,断开与服务器 A 的连接,建立与服务器 B 的 SQL 连接,最后向服务器 B 发出请求。但是,当异步性开始发挥作用时并且 SQL 是由并发请求触发的,我有问题。
希望我只是愚蠢,因为我是异步代码的新手,请赐教!谢谢!
我想我会更新这个以防其他人遇到类似的问题。@AlwaysLearning 为我提供了一个链接,指向 mssql npm 文档的一部分,该文档解释了连接池,并在需要访问多个数据库时这样做。我建议通读一遍。
原来mssql的.connect()函数是全局的。如果调用 .connect() 函数时全局池已经连接,它将解析为已经连接的池。这给我带来了麻烦,因为当快速连续发送两个请求时,我的应用程序中会发生以下情况:
为了解决这个问题,您需要开发一些连接池管理代码。通过这种方式,您可以确保每个必需的数据库连接都有单独的连接池。此外,这是一种加快查询速度的简单方法,因为您不需要每次发出请求时都重新连接到数据库。
npm 文档提供了几个示例帮助文件,但我发现它们对我来说并不理想,而且我无法在我的环境中编译所有代码。我将代码自定义为以下内容:
mssql-connection-pooling.js:
const { ConnectionPool } = require('mssql')
const pools = {}
// create a new connection pool
function CreatePool(config) {
let key = JSON.stringify(config)
if (GetPool(key))
throw new Error('Pool already exists')
pools[key] = (new ConnectionPool(config)).connect()
return pools[key]
}
// get a connection pool from all pools
function GetPool(name) {
if (pools[name])
return pools[name]
else
return null
}
// if pool already exists, return it, otherwise create it
function GetCreateIfNotExistPool(config) {
let key = JSON.stringify(config)
let pool = GetPool(key)
if(pool)
return pool
else
return CreatePool(config)
}
// close a single pool
function ClosePool(config) {
let key = JSON.stringify(config)
if (pools[key]) {
const pool = pools[key];
delete pools[key];
pool.close()
return true
}
return false
}
// close all the pools
function CloseAllPools() {
pools.forEach((pool) => {
pool.close()
})
pools = {}
return true
}
module.exports = {
ClosePool,
CloseAllPools,
CreatePool,
GetPool,
GetCreateIfNotExistPool
}
我创建了 GetCreateIfNotExistPool() 函数,您提供了一个数据库连接配置对象。该函数检查池中是否为给定的连接配置存储了一个打开的连接。如果有,它只返回连接池。如果没有,它会创建它然后返回它。
用法示例:
const sql = require("mssql");
let mssql = require('./mssql-pool-management.js')
let exampleDBConfigA = {
user: 'test',
password: 'password,
server: 'SqlServerA',
database: 'DatabaseA'
};
let exampleDBConfigB = {
user: 'test',
password: 'password,
server: 'SqlServerB',
database: 'DatabaseB'
};
...
// Request 1
try {
let sqlPool = await mssql.GetCreateIfNotExistPool(exampleDBConfigA)
let request = new sql.Request(sqlPool)
// query code
}
catch(error) {
//error handling
}
...
// Request 2
try {
let sqlPool = await mssql.GetCreateIfNotExistPool(exampleDBConfigB)
let request = new sql.Request(sqlPool)
// query code
}
catch(error) {
//error handling
}
在这个例子中,请求 1 和 2 可以同时调用,它们的连接不会干扰!
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句