Skip to content
Advertisement

Query works but cant retrieve the data

I am new to Node.js (3 days total experience). I am using Node.js and the tedious package to query a database (azure SQL). I use the example as explained here: https://docs.microsoft.com/en-us/azure/azure-sql/database/connect-query-nodejs?tabs=macos

const connection = new Connection(config);

// Attempt to connect and execute queries if connection goes through
connection.on("connect", err => {
    if (err) {
        console.error(err.message);
    } else {
        console.log("Reading rows from the Table...");

        // Read all rows from table
        const request = new Request(
            "SELECT * FROM clients",
            (err, rowCount, columns) => {
                if (err) {
                    console.error(err.message);
                } else {
                    console.log(`${rowCount} row(s) returned`);
                }
            }
        );

        request.on("row", columns => {
            columns.forEach(column => {
                console.log("%st%s", column.metadata.colName, column.value);
            });
        });

        connection.execSql(request);
    }
});

I have two issues:

  1. I do not know how to get the queried data into an object and
  2. If I run the script it does print the items to the console, but it doesn’t close the connection after it has done so. If I add a connection.close() at the bottom, it will close the connection before its done. I get the feeling that node.js executes everything at the same time (I am used to Python..).

Update
I found a way to close the connection, to my understanding the request object has several “events” that are predefined by the library. It seems I need to add the event “done” through request.on('done', ...) in order to make sure that it can even BE done. My updated code looks like this:

var connection = new Connection(config);

connection.connect(function(err) {
        // If no error, then good to go...
        executeStatement();
    }
);

connection.on('debug', function(text) {
        //remove commenting below to get full debugging.
        //console.log(text);
    }
);

function executeStatement() {
    request = new Request("SELECT * FROM clients", function(err, rowCount) {
        if (err) {
            console.log(err);
        } else {
            console.log(rowCount + ' rows');
        }

        connection.close();
    });

    request.on('row', function(rows) {
        _.forEach(rows, function(value, collection){
            console.log(value)
            console.log(value.value);
            console.log(value.metadata.colName)
            console.log(collection)
        })
    });

    request.on('done', function(rowCount, more) {
        console.log(rowCount + ' rows returned');
    });

    // In SQL Server 2000 you may need: connection.execSqlBatch(request);
    connection.execSql(request);
}

Anyways, your help would be much appreciated!

Regards Pieter

Advertisement

Answer

The package tedious is synchronous package, it uses the callback to return results. So when we call connection.close(), it will disable connection and stop the callback function. If will want to close the connection, I suggest you use async package to implement it.

For example

const { Connection, Request } = require("tedious");
const async = require("async");
const config = {
  authentication: {
    options: {
      userName: "username", // update me
      password: "password", // update me
    },
    type: "default",
  },
  server: "your_server.database.windows.net", // update me
  options: {
    database: "your_database", //update me
    encrypt: true,
    validateBulkLoadParameters: true,
  },
};

const connection = new Connection(config);
let results=[]
function queryDatabase(callback) {
  console.log("Reading rows from the Table...");

  // Read all rows from table
  const request = new Request("SELECT * FROM Person", (err, rowCount) => {
    if (err) {
      callback(err);
    } else {
      console.log(`${rowCount} row(s) returned`);
      callback(null);
    }
  });
  
  request.on("row", (columns) => {
     let result={}
    columns.forEach((column) => {
     
      result[column.metadata.colName]=column.value
      console.log("%st%s", column.metadata.colName, column.value);
    });
    // save result into an array
     results.push(result)
  });

  connection.execSql(request);
}
function Complete(err, result) {
  if (err) {
    callback(err);
  } else {
    connection.close();
    console.log("close connection");
  }
}
connection.on("connect", function (err) {
  if (err) {
    console.log(err);
  } else {
    console.log("Connected");

    // Execute all functions in the array serially
    async.waterfall([queryDatabase], Complete);
  }
});
connection.connect();

enter image description here

Besides, you also can use the package mssql. It supports asynchronous methods and depends on package tedious. We can directly call close after querying.

For example

const mssql = require("mssql");
const config = {
  user: "username",
  password: "password",
  server: "your_server.database.windows.net",
  database: "your_database",
  options: {
    encrypt: true,
    enableArithAbort: true,
  },
};
let pool = new mssql.ConnectionPool(config);

async function query() {
  try {
    await pool.connect();
    const request = pool.request();
    const result = await request.query("SELECT * FROM Person");
    console.dir(result.recordset);

    await pool.close();
    console.log(pool.connected);
  } catch (error) {
    throw error;
  }
}

query().catch((err) => {
  throw err;
});

enter image description here

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement