I am trying to connect to my Azure SQL DB from an azure function written in nodeJS. I have set the connection strings in the application settings and it still does not work. I used ODBC key for connection settings. Did anyone try this? Below is the sample code for my function
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
// Create connection to database
const config = process.env["sqldb_connection"];
var connection = new Connection(config);
// Attempt to connect and execute queries if connection goes through
connection.on('connect', function(err)
{
if (err)
{
console.log(err)
}
else
{
queryDatabase()
}
}
);
function queryDatabase()
{ console.log('Reading rows from the Table...');
// Read all rows from table
request = new Request(
"SELECT ORG_ID,ORG_NAME FROM org",
function(err, rowCount, rows)
{
console.log(rowCount + ' row(s) returned');
process.exit();
}
);
request.on('row', function(columns) {
columns.forEach(function(column) {
console.log("%s\t%s", column.metadata.colName, column.value);
});
});
connection.execSql(request);
}
I am getting an error saying
Exception while executing function: Functions.HttpTriggerJS2. mscorlib: The given key was not present in the dictionary.
Run the npm install tedious command in the Kudu remote execution console under D:\home\site\wwwroot.
In Azure Functions, all of your code should be put inside the module.exports function.
You should use context.log() instead of console.log().
You really don't have to set the connection settings string in Application settings of the function.
You should inform the runtime when your code has finished by calling context.done().
The following code works for me:
var Connection = require('tedious').Connection;
var Request = require('tedious').Request;
module.exports = function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
var config = {
userName: '<userName>',
password: '<password>',
server: '<AzureSQLDBName>.database.windows.net',
// If you're on Windows Azure, you will need this:
options:
{
database: 'your DB',
encrypt: true
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
context.log(err);
context.res = {
status: 500,
body: "Unable to establish a connection."
};
context.done();
} else {
executeStatement();
}
});
function executeStatement() {
request = new Request("select 42, 'hello world'", function(err, rowCount) {
if (err) {
context.log(err);
context.res = {
status: 500,
body: "Failed to connect to execute statement."
};
context.done();
} else {
context.log(rowCount + ' rows');
}
});
request.on('row', function(columns) {
columns.forEach(function(column) {
context.log(column.value);
});
context.done();
});
connection.execSql(request);
}
};
For more information, see Azure Functions JavaScript developer guide.
Related
Im using Tedious in Node JS to return a simple SQL Query :
var Connection = require('tedious').Connection;
var config = {
server: 'myserver.database.windows.net',
authentication: {
type: 'default',
options: {
userName: 'myusername',
password: 'mypassword',
rowCollectionOnDone: true,
rowCollectionOnRequestCompletion: true
}
},
options: {
encrypt: true,
database: 'mydatabase'
}
};
const connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log(err);
}else{
console.log("Connected");
}
});
var Request = require('tedious').Request
var TYPES = require('tedious').TYPES;
let results = [];
function checkId(cid) {
request = new Request("SELECT * FROM mytable WHERE id = #cid",function(err, rowCount, rows) {
if (err) {
console.log(err);
}
});
request.addParameter('cid', TYPES.NVarChar, cid);
request.on('row', function(row) {
results.push(row);
});
console.log(results) // I can see results array perfectly here
connection.execSql(request);
//return callback(null, results); // Tried setting callback as parameter too in this function but got error "callback is not a function"
}
When I call the statement function outside like this:
var sqlquery = new checkId(passid);
console.log(sqlquery);
I get:
"sqlquery {}"
I other words, an [object Object] but empty (obviously, JSON.strinfigy in empty it's useless). I already tried to use callback as a workaround as commented in the code above but got error, how can I see results array when I call the function ?
Knowing that Tedious it's async and results won´t process on time to get them outside (reason why it´s empty object) and since there´s no specific answer to this anywhere (a lot of theory yes, but not a clear explanation due that some code it´s outdated like curiosly where you use callback as a set function, there´s no guidance of how to mix promises with Tedious properly, answers only show results in console.log or some people may be beginners with the sync/async concept), I post here a commented way that worked for me in case anyone may need it:
///Connection
var Connection = require('tedious').Connection;
var config = {
server: 'myserver.database.windows.net',
authentication: {
type: 'default',
options: {
userName: 'myusername',
password: 'mypassword',
rowCollectionOnDone: true,
rowCollectionOnRequestCompletion: true
}
},
options: {
encrypt: true,
database: 'mydatabase'
}
};
const connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log(err);
}else{
console.log("Connected");
}
});
var Request = require('tedious').Request
var TYPES = require('tedious').TYPES;
Now , inside an async function you can call this example query with params (must be inside async function in order to use 'return await' and that everything syncs to avoid empty data :
async your_function(){
var id = 'id you want or user inputs';
const allData = [];
// We now set the promise awaiting it gets results
await new Promise((resolve,reject) => {
const request = new Request("SELECT * FROM table WHERE field = #id", function(err, rowCount) {
if (err) {
return reject(err);
} else {
console.log(rowCount + ' rows');
}
});
request.addParameter('id', TYPES.NVarChar, id); //Param id declaration
request.on('row', function(columns) {
columns.forEach(function(column) {
allData.push(column.value); //Push the result to array
});
});
request.on('doneProc', function (rowCount, more, returnStatus, rows) {
console.log('onDoneProc');
return resolve(allData); //Here we resolve allData using promise in order to get it´s content later
});
connection.execSql(request);
});
var mydata = allData; // Now You can assign it or use the same object as well
}
Hope it helps someone as it did to me.
I am trying to write a code to connect with snowflake inside the azure function app using nodejs stack. Here is the code I have writtern.
async function af2snf()
{
console.log("starting connection");
var snowflake = require('snowflake-sdk');
// Create a Connection object that we can use later to connect.
console.log("prep conn");
var connection = snowflake.createConnection( {
account: "myaccountname",
username: "myusername",
password: "mypass",
database: "dbname",
schema: "schemaname"
}
);
console.log("making connection");
var conn_id = connection.connect(
function(err, conn) {
if (err) {
console.error('Unable to connect: ' + err.message);
}
else {
console.log('Successfully connected to Snowflake.');
// Optional: store the connection ID.
connection_ID = conn.getId();
}
}
)
return conn_id.getId();
}
console.log("outside fucntion");
console.log(af2snf());
console.log("executed fucntion");
The output I am getting is :
outside fucntion
starting connection
prep conn
making conn
Promise { <pending> }
executed fucntion
Successfully connected to Snowflake.
But What I need is :
outside fucntion
starting connection
prep conn
making conn
Successfully connected to Snowflake.
Promise { <pending> }
executed fucntion
I am very new to nodejs. Please help me out on this
af2nsf needs to return a promise :
async function af2snf() {
return new Promise((resolve,reject)=>{
console.log("starting connection");
var snowflake = require('snowflake-sdk');
// Create a Connection object that we can use later to connect.
console.log("prep conn");
var connection = snowflake.createConnection( {
account: "myaccountname",
username: "myusername",
password: "mypass",
database: "dbname",
schema: "schemaname"
});
console.log("making connection");
connection.connect( async function(err, conn) {
if (err) {
console.error('Unable to connect: ' + err.message);
return reject(err);
}
else {
console.log('Successfully connected to Snowflake.');
// Optional: store the connection ID.
var conn_id = await conn.getId();
return resolve(conn_id);
}
})
});
}
console.log("outside fucntion");
af2snf().then(conn_id=>{
console.log(conn_id);
console.log("executed fucntion");
}).catch(err=>{
console.error(err);
});
I am having problem with sql query execution using callback, I never worked on the node.js, so looking for some guidance and get going.
Tried with having database connection in same file, but unable to execute when having the database connection in another file.
DatabaseManager.js
var Tedious = require('tedious');
var Connection = Tedious.Connection;
var Request = Tedious.Request;
function connect(cb) {
var config = {
userName: 'dddff',
password: 'fsfdsf',
server: '12345.database.windows.net',
options:
{
database: '12345',
encrypt: true
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
if (err) {
console.log(err);
return;
}
console.log('CONNECTED TO DATABASE');
cb(connection);
});
}
module.exports = connect;
app.js
var connect = require('./DatabaseManager');
bot.dialog('profileDialog', (session) => {
session.send('Hello Message', session.message.text);
console.log('Creating a connection');
connect(function(connection) {
console.log('Reading rows from the Table.');
// Execute queries here and how to frame the syntax here?
connection.query("select FNAME from StudentProfile where ID=1"),
function(err, result, fields) {
if (err) throw err;
console.log(result);
}
});
})
I expect the output of select statement result on the console.
My 'handler.js' functions connects to the Postgres database and performs few queries using node.js. My function worked successfully in local, but when accessed as AWS lambda, the queries don't work.
I have also added the corresponding vpc security groups and subnet ids in 'serverless.yml'.
The error logs in 'Cloudwatch' just shows the console.log statements before and after queries and the function terminates with timed out error. I could not figure out the issue.
I have attached the example 'handler.js' code below:
var { Pool, Client } = require('pg');
export function apiTest(event, context, callback) {
var connectionString = 'postgresql://username:password#database.server.com:xxxx/dbname';
var client = new Client({
connectionString: connectionString,
})
client.connect();
console.log('Connected to PostgreSQL database');
client.query('SELECT * from table', (err, res) => {
console.log("inside query");
var jsonString = JSON.stringify(res.rows);
var jsonObj = JSON.parse(jsonString);
const headers = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": true
};
// Return status code 500 on error
if (err) {
const response = {
statusCode: 500,
headers: headers,
body: JSON.stringify({
status: false
})
};
callback(null, response);
client.end();
return;
}
const response = {
statusCode: 200,
headers: headers,
body: JSON.stringify(jsonObj)
};
callback(null, response);
console.log("query success")
client.end()
context.succeed(context);
})
}
I am using oracledb npm package to establish connection with the DB when creating a node.js backend API. I am able to obtain the result when I do console.log(result.rows)
Below is the function code
getDbConnection: function(query) {
var connectInfo= [EnvConfig.getConnectionHostName(), EnvConfig.getConnectionPort()]; // Array of hostname and port
var connectHost = connectInfo.join(':'); // join hostname and port with ':'
var connectionAttr = [connectHost, EnvConfig.getConnectionSID()]; // hostname:port and SID
var connectString = connectionAttr.join('/'); // creating the connection string like 'hostname:port'
console.log(connectString);
// creating a oracle connection
oracledb.getConnection(
{
user: EnvConfig.getConnectionUserName(),
password: EnvConfig.getConnectionPassword(),
connectString: connectString
},
function (err, connection) {
if(err) {
console.log(err.message);
return;
}
connection.execute(
query, function(err, result) {
if(err) {
console.log(err.message);
return;
}
console.log(result.rows); // I get result here
return result.rows; // return result on success
}
);
}
);
}
I call the getDbConnection function from other file and when I console.log() like console.log(getDbConnection(query)) . I get the result as undefined. How do I solve this.
you can't get your data like this. Return like this will not gonna work here
Since it works in async nature, you can do one thing to use a callback function to get that result like this
DbConnection: function(query,callback) {//pass callback as parameter
var connectInfo = [EnvConfig.getConnectionHostName(), EnvConfig.getConnectionPort()]; // Array of hostname and port
var connectHost = connectInfo.join(':'); // join hostname and port with ':'
var connectionAttr = [connectHost, EnvConfig.getConnectionSID()]; // hostname:port and SID
var connectString = connectionAttr.join('/'); // creating the connection string like 'hostname:port'
console.log(connectString);
// creating a oracle connection
oracledb.getConnection({
user: EnvConfig.getConnectionUserName(),
password: EnvConfig.getConnectionPassword(),
connectString: connectString
},
function(err, connection) {
if (err) {
console.log(err.message);
return callback(err);
}
connection.execute(
query,
function(err, result) {
if (err) {
console.log(err.message);
return callback(err);
}
console.log(result.rows); // I get result here
return callback(null,result.rows); // return result on success
}
);
}
);
}
And call like this
//Use your function with callback
getDbConnection(query,function(err,result){
if(!err){
console.log(result)
}
})