Node-mssql: Resolve array of queries in one Transaction

Created on 28 May 2015  路  12Comments  路  Source: tediousjs/node-mssql

Using a global connection like here #164 for use Transaction. I think this works but how i can do to resolve a array of queries using transaction or multiples transactions, the code i put works only for one querie.

routes/set1Transaction.js

var sql     = require('mssql');

module.exports = function(globalConnection) {
   return function(req, res, next) {
      var transaction = new sql.Transaction(globalConnection);
      transaction.begin(function(err) {
          // ... error checks

             var request = new sql.Request(transaction);
             request.query('insert into mytable (mycolumn) values (12345)', function(err, recordset) {
                 // ... error checks

             transaction.commit(function(err, recordset) {
                  // ... error checks

              console.log("Transaction commited.");
                  });
            });
       });
       req.results=recordset;
       next();

    }

};
discussion

Most helpful comment

I found this during my solution research and I think for v4.x this is nicer with ES6 and async/await

    const transaction = await new sql.Transaction()
    transaction.begin(async err => {
      try{
        const request = new sql.Request(transaction)
        const result1 = await request.query`query1`
        const result = await request.query`query2`
        transaction.commit(tErr => tErr && next('transaction commit error'))
      }catch(err){
        transaction.rollback(tErr => tErr && next('transaction rollback error'))
        next('unknown error inside transaction = rollback')
      }
    })

All 12 comments

Try this:

var sql = require('mssql');

module.exports = function(globalConnection) {
    return function(req, res, next) {
        var transaction = new sql.Transaction(globalConnection);
        transaction.begin(function(err) {
            // ... error checks

            var request = new sql.Request(transaction);
            request.query('insert into mytable (mycolumn) values (12345)', function(err, recordset) {
                // ... error checks

                transaction.commit(function(err) {
                    // ... error checks

                    console.log("Transaction commited.");
                    req.results = recordset;
                    next();
                });
            });
        });
    }
};

The question goes for the line of what happen if i want to do make two queries or array of queries. Somethinkg like this:

ar sql = require('mssql');

module.exports = function(globalConnection) {
    return function(req, res, next) {
        var transaction = new sql.Transaction(globalConnection);
        transaction.begin(function(err) {
            // ... error checks

            var request = new sql.Request(transaction);
            request.query('insert into mytable (mycolumn) values (12345)', function(err, recordset) {
                // ... error checks

                   //MULTIPLES QUERIE HERE BEFORE COMMIT
                    request.query2(...)
                    request.query3(...)

                transaction.commit(function(err) {
                    // ... error checks

                    console.log("Transaction commited.");
                    req.results = recordset;
                    next();
                });
            });
        });
    }
};

Sorry, how can i make two queries in one transaction at least?, not works for me :/

Here is my try...

module.exports = function(globalConnection) {
    return function(req, res) {

      var results=[];
        var transaction = new sql.Transaction(globalConnection);
        transaction.begin(function(err) {
            // ... error checks

            var request = new sql.Request(transaction);
            request.query('SELECT 1', function(err, recordset) {
              results.push(recordset);
                // ... error checks

                request.query('SELECT 1', function(err, recordset) {
                  results.push(recordset);
                    // ... error checks

                    transaction.commit(function(err) {
                        // ... error checks

                        console.log("Transaction commited.");
                        console.log(results);
                        res.status(200).json(results: results);
                    });
                });
            });
        });
    }
};

This works, but how can i make this more dynamicall like works with an array of queries for example.
The results is:

"results": [
[
{
"": 1
}
],
[
{
"": 1
}
]
]

How about using async

var sql = require('mssql');
var async = require('async');

var transaction = new sql.Transaction(globalConnection);
transaction.begin(function(err) {
    if (err) {
        return console.error('Error in transaction begin', err);
    }

    var request = new sql.Request(transaction);

    async.series({
        one: function(callback){
            request.query('SELECT 1 as a', callback);
        },
        two: function(callback){
            request.query('SELECT 2 as b', callback);
        }
    },
    function(err, results) {
        // results is now equal to: {one: [{a: 1}], two: [{b: 2}]}
        if (err) {
            console.error('Error in queries, rolling back', err);
            return transaction.rollback();
        }
        transaction.commit(function(err) {
            if (err) {
                return console.error('Error in commit', err);
            }
            console.log("Transaction commited.");
            console.log(results);
        });
    });
});

_Untested code_

If you have an array of queries, you can use async.each if you want to execute them in parallel or async.eachSeries if you want to run them consecutively. Both have a final callback function where you can commit or rollback the transaction.

That actually works, but my try with async.eachSeries doesnt xD.

var sql = require('mssql');
var async = require('async');
var transaction = new sql.Transaction(globalConnection);
var resultsList=[];

      transaction.begin(function(err) {
      if (err) {
          return console.error('Error in transaction begin', err);
      }

      var request = new sql.Request(transaction);

      var hugeArray= ['SELECT 1 as a', 'SELECT 1 as b'];
      async.eachSeries(hugeArray, function iterator(item, callback) {
          console.log(item);
          request.query(item, callback);


      },
      function(err, results) {

          if (err) {
              console.error('Error in queries, rolling back', err);
              return transaction.rollback();
          }
   // Here i try push the results
          resultsList.push(results);
          transaction.commit(function(err) {
              if (err) {
                  return console.error('Error in commit', err);
              }
              console.log("Transaction commited.");

              next();
          });
      }
    );
  });

@estvmachine What doesn't work? Your code looks fine. What did you expect and what is your actual result?

Ah sorry, the actual result is a list of undefined.

@estvmachine essentially your code is fine. I feel my work is done explaining how you can approach the problem. Now you may address your own development skills and debug. And when you're done debugging and still have a problem, you could ask a question at Stackoverflow or post a new issue here if you think something is broken with mssql.

Yeah you are right, thanks for the advice.

Hi, only im passing for says thanks and told how i resolved this, i used a constructor function named 'setUpMultipleQueries', is a forEach using the 'listQuery'. Well i leave the code. Thanks!

var sql = require('mssql');
var async = require('async');

var transaction = new sql.Transaction(globalConnection);
transaction.begin(function(err) {
    if (err) {
        return console.error('Error in transaction begin', err);
    }

      var request = new sql.Request(transaction);
      var listQuery= setUpMultipleQueries(req.consultas, request);  /*HERE IS THE MAGIC*/

      async.series( listQuery,

    function(err, results) {
        // results is now equal to: {one: [{a: 1}], two: [{b: 2}]}
        if (err) {
            console.error('Error in queries, rolling back', err);
            return transaction.rollback();
        }
        transaction.commit(function(err) {
            if (err) {
                return console.error('Error in commit', err);
            }
            console.log("Transaction commited.");
            console.log(results);
        });
    });
});

function setUpMultipleQueries(listQuery, request){
  var requestObject= {};
  listQuery.forEach(function(query, index){
    console.log(index);
      requestObject['q'+index]= function(callback){
            request.query(query, callback);
      };
  });
  return requestObject;
};


I found this during my solution research and I think for v4.x this is nicer with ES6 and async/await

    const transaction = await new sql.Transaction()
    transaction.begin(async err => {
      try{
        const request = new sql.Request(transaction)
        const result1 = await request.query`query1`
        const result = await request.query`query2`
        transaction.commit(tErr => tErr && next('transaction commit error'))
      }catch(err){
        transaction.rollback(tErr => tErr && next('transaction rollback error'))
        next('unknown error inside transaction = rollback')
      }
    })
Was this page helpful?
0 / 5 - 0 ratings

Related issues

brilvio picture brilvio  路  3Comments

PatrikFomin picture PatrikFomin  路  6Comments

aerze picture aerze  路  3Comments

linvi picture linvi  路  3Comments

jeetendra-choudhary picture jeetendra-choudhary  路  3Comments