2

我正在尝试将 NodeJS 与 Tedious ( http://pekim.github.io/tedious/ ) sql server 插件一起使用来进行多个数据库调用。我的意图是: 1. 打开一个连接 2. 启动一个事务 3. 进行多个数据库(存储过程)调用,不会返回任何数据。4. 提交事务(或错误回滚)。5.关闭连接

这是 NodeJS 的示例 .js 文件(不使用事务),我在其中尝试进行多个数据库调用,但失败并出现错误“请求只能在 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!');
4

4 回答 4

3

您正在尝试在未建立的连接上执行语句。在调用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.");
        });
    });
});
于 2014-12-01T19:47:22.600 回答
1

您应该使用繁琐的连接池来创建一个包含多个连接的池。对于 node js,一个 npm 模块位于:https ://www.npmjs.com/package/tedious-connection-pool

对于 for 循环中的每个新值,您都可以获得一个新连接并connection.resetdoneInProc事件中使用。您一直在做的情况是正确执行 for 循环的第一次迭代(LoggedIn State),并且在没有关闭或释放连接的情况下继续使用相同的连接对象(SentClientRequest state)。因此,当代码到达 for 循环的第二次迭代时,同一对象处于最终状态。希望它能解决你的问题

于 2017-06-29T13:26:58.773 回答
0

您可以使用繁琐的连接池https://github.com/pekim/tedious-connection-pool

于 2014-12-23T08:16:01.343 回答
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
}

于 2020-01-08T18:01:28.923 回答