我正在尝试将NodeJS与Tedious(http://pekim.github.io/tedious/)sql server插件一起使用来进行多个数据库调用。我的意图是: 1.打开连接 2.开始交易 3.进行多个数据库(存储过程)调用,这些调用不会返回任何数据。 4.提交事务(或在错误时回滚)。 5.关闭连接
这是一个示例.js文件,(不使用事务)用于NodeJS,我试图进行多个数据库调用,并且失败并显示错误“请求只能在LoggedIn状态下进行,而不是在SentClientRequest状态下进行“。我没有尝试解决这个问题。
有谁知道如何解决这个问题?
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
var config = {
userName: 'login',
password: 'password',
server: '127.0.0.1',
options: { rowCollectionOnDone: true }
};
var max = 1;
for (var i = 0; i < max; i++) {
var connection = new Connection(config);
function executeStatement() {
request = new Request("select 42, 'hello world'", function (err, rowCount) {
if (err) {
console.log(err);
} else {
console.log(rowCount + ' rows');
}
});
request.on('row', function (columns) {
columns.forEach(function (column) {
console.log(column.value);
});
});
request.on('doneInProc', function (rowCount, more, rows) {
});
request.on('doneProc', function (rowCount, more, rows) {
console.log('statement completed!')
connection.execSql(request);
});
request.on('returnStatus', function (status) {
console.log('statement completed!')
});
connection.execSql(request);
}
connection.on('connect', function (err) {
// If no error, then good to go...
executeStatement();
});
}
console.log('Done!');
答案 0 :(得分:2)
您尝试在未建立的连接上执行语句。在致电executeStatement
之前,您错过了错误处理程序。
connection.on('connect', function (err) {
if (err) {
console.log(err); // replace with your code
return;
};
// If no error, then good to go...
executeStatement();
});
修改强>
如何在串行事务中执行多个语句:
var statements = ["select 1", "select 2", "select 3"];
var transaction = new sql.Transaction(connection);
transaction.begin(function(err) {
// ... error checks
async.mapSeries(statements, function(statement, next) {
var request = new sql.Request(transaction);
request.query(statement, next);
}, function(err, results) {
// ... error checks
transaction.commit(function(err, recordset) {
// ... error checks
console.log("Transaction commited.");
});
});
});
答案 1 :(得分:0)
答案 2 :(得分:0)
您应该使用繁琐的连接池来创建多个连接池。 对于节点js,可在以下位置使用npm模块:https://www.npmjs.com/package/tedious-connection-pool
对于for循环中的每个新值,您可以获取新连接并在connection.reset
事件上使用doneInProc
。
您一直在做的情况是正确执行for循环的第一次迭代(LoggedIn State
),并且在没有关闭或释放连接的情况下继续使用相同的连接对象(SentClientRequest state
)。
因此,当代码到达for循环的第二次迭代时,相同的对象处于最终状态。
希望它能解决你的问题
答案 3 :(得分:0)
正如@zevsuld和@mannutech所说,乏味的连接池将启用多个连接,并防止同时请求进入您的服务器时出错。
下面是一个通用示例,它允许您在一个连接池中编写多个查询,并公开它们以供您的api使用。我只是添加这个,以防其他人来尝试完成这种实现。
const ConnectionPool = require('tedious-connection-pool');
const path = require('path');
require('dotenv').config({
path: path.join(__dirname, '../../.env')
})
let Request = require('tedious').Request;
let poolConfig = {
min: 10,
max: 50,
log: true
}
let connectionConfig = {
userName: process.env.user,
password: process.env.password,
server: process.env.server
};
//create the pool
let pool = new ConnectionPool(poolConfig, connectionConfig);
pool.on('error', function(err) {
console.error(err);
});
// At this point in the code, we have established a connection pool. If you run node, you'll see it log out all then connections to your database.
// Let's add some methods which your server might use in fulfilling requests to various endpoints.
let query1 = (cb, res, query) => {
// acquire a connection:
pool.acquire(function(err, connection) {
if (err) {
console.error(err);
return;
} else {
// form your query
let sql_query = `SELECT column1, colum2 from TABLE WHERE column1 LIKE '${query.param}%%' ORDER BY column1 ASC`
// use the connection as usual:
request = new Request(sql_query, (err, rowCount) => {
if (err) {
console.log(err);
return;
} else {
// console.log('rowCount:', rowCount);
}
//release the connection back to the pool when finished
connection.release();
});
let records = [];
request.on("row", function(columns) {
let rowArray = [];
columns.forEach(function(column) {
rowArray.push(column.value);
});
records.push(rowArray);
});
request.on("doneInProc", function() {
cb(records, res);
});
// lastly exectue the request on the open connection.
connection.execSql(request);
}
});
};
let query2 = (cb, res, query) => {
// acquire a connection:
pool.acquire(function(err, connection) {
if (err) {
console.error(err);
return;
} else {
// form your query
let sql_query = `SELECT column3, colum4 from TABLE2 WHERE column3 LIKE '${query.param}%%' ORDER BY column3 ASC`;
// use the connection as usual:
request = new Request(sql_query, (err, rowCount) => {
if (err) {
console.log(err);
return;
} else {
// console.log('rowCount:', rowCount);
}
//release the connection back to the pool when finished
connection.release();
});
let records = [];
request.on("row", function(columns) {
let rowArray = [];
columns.forEach(function(column) {
rowArray.push(column.value);
});
records.push(rowArray);
});
request.on("doneInProc", function() {
cb(records, res);
});
// lastly exectue the request on the open connection.
connection.execSql(request);
}
});
};
// Let's expose these two functions to the rest of your API:
module.exports = {
query1,
query2
}