I am building an API integration application in Node.js using the "mssql" package. I have the data pulling from the third-party API, and stored in my SQL Server. However, my DB connection stays open forever and keeps my app running. Everything that I have tried ends the connection before the data can be stored. So, I can either store my data and keep the connection open forever, or end my connection and not store the data. The best that I have found is something like this answer: https://stackoverflow.com/a/45681751/5552707.
And I have tried that in my app, which still kills my connection before data is stored:
sql.connect(sqlConfig).then(pool => {
var request = new sql.Request(pool);
var result = request.bulk(table, (err, result) => {
if(err){
console.log("fail. " + err);
return;
}
})
}).catch(err => {
console.log('There was an error processing the request. ' + err);
}).then(() => {
console.log('done');
process.exit(1);
});
They docs don't explain how to do this, which is frustrating.
Any ideas would be awesome!
Thanks!
Adding
process.exit();
to the callback function did the trick.
var request = new sql.Request(pool);
var result = request.bulk(table, (err) => {
if(err){
console.log("fail. " + err);
return;
}
process.exit(1);
})
Related
I am developing a flutter application in which I am implementing hive database for caching data.
I have added both hive and hive_flutter packages.
I am getting data from APIs and store that to hive to update data, It works fine when I used app connected to internet but didn't works when I try to read while being offline. Here is the code of my API method I am calling to get data:
static Future<List<UserPost>> getPosts() async {
//I call my API in try block, if its successful, I update the data in hive
List<UserPost> posts = [];
Hive.openBox(Constants.APIDATA_BOX);
try {
var response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'),);
if (response.statusCode == 200) {
//Clear hive box from old data
Hive.box(Constants.APIDATA_BOX).clear();
Hive.box(Constants.APIDATA_BOX).put(Constants.API_DATA,jsonDecode(response.body));
}
} catch (e) {
print('You are not connected to internet');
}
//I am getting data here from hive database and it works fine while connected to internet
var listMaps =await Hive.box(Constants.APIDATA_BOX).get(Constants.API_DATA, defaultValue: []);
posts = listMaps.map<UserPost>((map) {
//Here flow stucked whenever working offline,
//Data is also available but here conversion cause error, I have tried many way but fails.
return UserPost.fromMap(map);
}).toList();
return posts;
}
I don't why I am getting error, I have tried many conversion ways here but all works while being online. Any help will be highly apprerciated.
I think I've understood the error but you should explain better which type of error you're having.
Anyway pay attention to the operations on Hive, which are often async, for example Hive.openBox(Constants.APIDATA_BOX);.
So when you have internet connection, you have to await for the response and Hive has time to open the box, otherwise it will throw an error so, considering the futures, you should do this:
static Future<List<UserPost>> getPosts() async {
List<UserPost> posts = [];
await Hive.openBox(Constants.APIDATA_BOX);
try {
var response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'),);
if (response.statusCode == 200) {
//Clear hive box from old data
await Hive.box(Constants.APIDATA_BOX).clear();
await Hive.box(Constants.APIDATA_BOX).put(Constants.API_DATA,jsonDecode(response.body));
}
} catch (e) {
print('You are not connected to internet');
}
var listMaps = await Hive.box(Constants.APIDATA_BOX).get(Constants.API_DATA, defaultValue: []);
posts = listMaps.map<UserPost>((map) {
return UserPost.fromMap(map);
}).toList();
return posts;
}
Note that await Hive.put() in a normal box is not strictly necessary, as explained in the docs
Been going round in circles for 2 days now.
I am getting some data from Azure SQL database (connection parameters are in sqlconfig)
function getCategories(callback) {
var conn = new mssql.ConnectionPool(sqlconfig);
var req = new mssql.Request(conn);
console.log('in getCategories');
conn.connect((err) => {
if (err) {
console.log('Connection Error:', err);
}
req.query("Select top 3 * from Categories", (err, rs) => {
if (err) {
console.log('Select error: ', err);
} else {
callback(rs.recordsets[0]);
}
conn.close();
});
})
}
I know the data is being returned correctly because when I do
getCategories((rs) => console.log('Get-Categories', rs));
I get the expected results
I am struggling to get the dataset to pass through to the view
app.get('/categories', (req, res) => {
res.render('categories.hbs', {
pageTitle: 'Catgories',
currentYear: new Date().getFullYear(),
categories: getCategories((rs) => rs)
});
});
returns nothing in the categories as it is undefined - so the callback has not finished running when the code is called.
How do I make the app.get wait until the getCategories has completed so that the data is ready to pass back to the view.
I found this post which let me to understand how this works
Need to keep promise result in a variable for Nodejs mssql validation
and have put my own answer in there. Short version is that in Node you have to set the variable value INSIDE the callback stack rather then returning it from the function to assign to the variable.
fetchDataFromDB('Select top 10 * from X', (err, res)=>{myvar = res})
How do I make the app.get wait until the getCategories has completed so that the data is ready to pass back to the view.
You could make the "getCategories" function a middleware that places the result on the request object that can then be obtained by the view. Simply call next() when the operation is complete and then render the view.
app.get('/categories', getCategories, (req, res) => {
res.render('categories.hbs', {
pageTitle: 'Catgories',
currentYear: new Date().getFullYear(),
categories: req.categories
});
});
I'm trying to call a register stored procedure from SQL Server. I'm using NodeJS with the mssql package. I got most of the code from the mssql Npm documentation. But it still doesn't work.
The code basically tries to initiate a ConnectionPool as a read the last update renamed connection to ConnectionPool, create a new request, introduce the parameters and the execute the stored procedure. I have it this way because I need to change the connection variable to another database every once in a while.
The error I get is:
ConnectionError: Connection is closed.
My code:
const sql = require('mssql');
const config = require('../config/dbPoly');
module.exports.registerUser = function(pUserName, pPassword, pNombre, pApellidos, pFK_TipoUsuario, callback) {
var connection = new sql.ConnectionPool(config);
var request = new sql.Request(connection);
request.input('input_parameter', sql.VARCHAR(25), pUserName);
request.input('input_parameter', sql.VARCHAR(16), pPassword);
request.input('input_parameter', sql.VARCHAR(25), pNombre);
request.input('input_parameter', sql.VARCHAR(50), pApellidos);
request.input('input_parameter', sql.Int, pFK_TipoUsuario);
request.execute('RegistrarUsuario', (err, result)=>{
if(err){
console.log(err);
}
else{
console.log(result);
}
});
};
There is this async version of implementation. Check if this serves your purpose
const sql = require('mssql');
const config = require('../config/dbPoly');
module.exports.registerUser = async function(pUserName, pPassword, pNombre, pApellidos, pFK_TipoUsuario) {
try {
let connection = await sql.connect(config)
let result = await connection.request()
.input('input_parameter', sql.VARCHAR(25), pUserName);
.input('input_parameter', sql.VARCHAR(16), pPassword);
.input('input_parameter', sql.VARCHAR(25), pNombre);
.input('input_parameter', sql.VARCHAR(50), pApellidos);
.input('input_parameter', sql.Int, pFK_TipoUsuario);
.execute('RegistrarUsuario');
return result;
} catch (err) {
console.log(err); // ... error checks
}
};
sql.on('error', err => {
// ... error handler
})
If someone else faces this problem, Prabodh's answer works perfectly.
I then faced another problem, it said the localhost was undefined in 1500ms. The reason was because my server field in the json config file had the following format: 'localhost\Server-Name'. I changed it just 'localhost' and problem fixed.
Also make sure your server has SQL Authentication enabled and not just Windows Authentication.
I am using the angular fullstack generator, but I do not believe this is the problem. I am working with Stripe.js and trying to save the data to the SQLite database using Sequelize. I have tried many different things, but the server stops running when it gets to the part where it is supposed to save the data.
app.post('/register', auth.isAuthenticated(), function(req,res){
console.log('access: ',req.query)
var userId = req.body._id
var data = req.body.data
//create stripe acct for artists
stripe.accounts.create(data, function(err,acct){
if(err){
console.log('err!!! ', err)
} else {
console.log('acct: ', acct)
//look for user in database
db.User.find({
where: {
_id: userId
}
})
.then(function(user) {
if(user){
console.log('user: ', user)
//add stripe acct info to db
console.log('acct:', user.dataValues.account);
/*this is where the Server stops running*/
user.updateAttributes({
account: JSON.stringify(acct)
}).success(function(){
console.log('newacct:', user.dataValues.account);
//just to see if it works
res.send({'account': acct});
})
} else {
console.log('no user found bruh')
}
});
}
})
})
I have tried redirecting, changing req.method to 'get' and then res.redirect. res.end() all of the above, but it always stops running. No errors are thrown it just simply says 'Stopping Express Server'. Thanks in advance for the help!
The question duplicates some older questions, but the things may have changed since then.
Is there some official support for connecting to SQL Server from Node.js (e.g. official library from MS)? Or at least some well-maintained third-party library appropriate for a production-grade application?
We usually use ASP.NET MVC/SQL Server combination, but currently I have a task for which express/Node.js seems to be more appropriate (and I'd like to play with something new), so the question is whether we can rely on a Node.js and SQL Server interaction.
UPD: It seems that Microsoft has, at last, released the official driver: https://github.com/WindowsAzure/node-sqlserver
This is mainly for future readers. As the question (at least the title) focuses on "connecting to sql server database from node js", I would like to chip in about "mssql" node module.
At this moment, we have a stable version of Microsoft SQL Server driver for NodeJs ("msnodesql") available here: https://www.npmjs.com/package/msnodesql. While it does a great job of native integration to Microsoft SQL Server database (than any other node module), there are couple of things to note about.
"msnodesql" require a few pre-requisites (like python, VC++, SQL native client etc.) to be installed on the host machine. That makes your "node" app "Windows" dependent. If you are fine with "Windows" based deployment, working with "msnodesql" is the best.
On the other hand, there is another module called "mssql" (available here https://www.npmjs.com/package/mssql) which can work with "tedious" or "msnodesql" based on configuration. While this module may not be as comprehensive as "msnodesql", it pretty much solves most of the needs.
If you would like to start with "mssql", I came across a simple and straight forward video, which explains about connecting to Microsoft SQL Server database using NodeJs here: https://www.youtube.com/watch?v=MLcXfRH1YzE
Source code for the above video is available here: http://techcbt.com/Post/341/Node-js-basic-programming-tutorials-videos/how-to-connect-to-microsoft-sql-server-using-node-js
Just in case, if the above links are not working, I am including the source code here:
var sql = require("mssql");
var dbConfig = {
server: "localhost\\SQL2K14",
database: "SampleDb",
user: "sa",
password: "sql2014",
port: 1433
};
function getEmp() {
var conn = new sql.Connection(dbConfig);
conn.connect().then(function () {
var req = new sql.Request(conn);
req.query("SELECT * FROM emp").then(function (recordset) {
console.log(recordset);
conn.close();
})
.catch(function (err) {
console.log(err);
conn.close();
});
})
.catch(function (err) {
console.log(err);
});
//--> another way
//var req = new sql.Request(conn);
//conn.connect(function (err) {
// if (err) {
// console.log(err);
// return;
// }
// req.query("SELECT * FROM emp", function (err, recordset) {
// if (err) {
// console.log(err);
// }
// else {
// console.log(recordset);
// }
// conn.close();
// });
//});
}
getEmp();
The above code is pretty self explanatory. We define the db connection parameters (in "dbConfig" JS object) and then use "Connection" object to connect to SQL Server. In order to execute a "SELECT" statement, in this case, it uses "Request" object which internally works with "Connection" object. The code explains both flavors of using "promise" and "callback" based executions.
The above source code explains only about connecting to sql server database and executing a SELECT query. You can easily take it to the next level by following documentation of "mssql" node available at: https://www.npmjs.com/package/mssql
UPDATE:
There is a new video which does CRUD operations using pure Node.js REST standard (with Microsoft SQL Server) here: https://www.youtube.com/watch?v=xT2AvjQ7q9E. It is a fantastic video which explains everything from scratch (it has got heck a lot of code and it will not be that pleasing to explain/copy the entire code here)
I am not sure did you see this list of MS SQL Modules for Node JS
Share your experience after using one if possible .
Good Luck
We just released preview driver for Node.JS for SQL Server connectivity. You can find it here:
Introducing the Microsoft Driver for Node.JS for SQL Server.
The driver supports callbacks (here, we're connecting to a local SQL Server instance):
// Query with explicit connection
var sql = require('node-sqlserver');
var conn_str = "Driver={SQL Server Native Client 11.0};Server=(local);Database=AdventureWorks2012;Trusted_Connection={Yes}";
sql.open(conn_str, function (err, conn) {
if (err) {
console.log("Error opening the connection!");
return;
}
conn.queryRaw("SELECT TOP 10 FirstName, LastName FROM Person.Person", function (err, results) {
if (err) {
console.log("Error running query!");
return;
}
for (var i = 0; i < results.rows.length; i++) {
console.log("FirstName: " + results.rows[i][0] + " LastName: " + results.rows[i][1]);
}
});
});
Alternatively, you can use events (here, we're connecting to SQL Azure a.k.a Windows Azure SQL Database):
// Query with streaming
var sql = require('node-sqlserver');
var conn_str = "Driver={SQL Server Native Client 11.0};Server={tcp:servername.database.windows.net,1433};UID={username};PWD={Password1};Encrypt={Yes};Database={databasename}";
var stmt = sql.query(conn_str, "SELECT FirstName, LastName FROM Person.Person ORDER BY LastName OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY");
stmt.on('meta', function (meta) { console.log("We've received the metadata"); });
stmt.on('row', function (idx) { console.log("We've started receiving a row"); });
stmt.on('column', function (idx, data, more) { console.log(idx + ":" + data);});
stmt.on('done', function () { console.log("All done!"); });
stmt.on('error', function (err) { console.log("We had an error :-( " + err); });
If you run into any problems, please file an issue on Github: https://github.com/windowsazure/node-sqlserver/issues
There is a module on npm called mssqlhelper
You can install it to your project by npm i mssqlhelper
Example of connecting and performing a query:
var db = require('./index');
db.config({
host: '192.168.1.100'
,port: 1433
,userName: 'sa'
,password: '123'
,database:'testdb'
});
db.query(
'select #Param1 Param1,#Param2 Param2'
,{
Param1: { type : 'NVarChar', size: 7,value : 'myvalue' }
,Param2: { type : 'Int',value : 321 }
}
,function(res){
if(res.err)throw new Error('database error:'+res.err.msg);
var rows = res.tables[0].rows;
for (var i = 0; i < rows.length; i++) {
console.log(rows[i].getValue(0),rows[i].getValue('Param2'));
}
}
);
You can read more about it here: https://github.com/play175/mssqlhelper
:o)
msnodesql is working out great for me. Here is a sample:
var mssql = require('msnodesql'),
express = require('express'),
app = express(),
nconf = require('nconf')
nconf.env()
.file({ file: 'config.json' });
var conn = nconf.get("SQL_CONN");
var conn_str = "Driver={SQL Server Native Client 11.0};Server=server.name.here;Database=Product;Trusted_Connection={Yes}";
app.get('/api/brands', function(req, res){
var data = [];
var jsonObject = {};
mssql.open(conn_str, function (err, conn) {
if (err) {
console.log("Error opening the connection!");
return;
}
conn.queryRaw("dbo.storedproc", function (err, results) {
if(err) {
console.log(err);
res.send(500, "Cannot retrieve records.");
}
else {
//res.json(results);
for (var i = 0; i < results.rows.length; i++) {
var jsonObject = new Object()
for (var j = 0; j < results.meta.length; j++) {
paramName = results.meta[j].name;
paramValue = results.rows[i][j];
jsonObject[paramName] = paramValue;
}
data.push(jsonObject); //This is a js object we are jsonizing not real json until res.send
}
res.send(data);
}
});
});
});
//start the program
var express = require('express');
var app = express();
app.get('/', function (req, res) {
var sql = require("mssql");
// config for your database
var config = {
user: 'datapullman',
password: 'system',
server: 'localhost',
database: 'chat6'
};
// connect to your database
sql.connect(config, function (err) {
if (err) console.log(err);
// create Request object
var request = new sql.Request();
// query to the database and get the records
request.query("select * From emp", function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
});
});
});
var server = app.listen(5000, function () {
console.log('Server is running..');
});
//create a table as emp in a database (i have created as chat6)
// programs ends here
//save it as app.js and run as node app.js
//open in you browser as localhost:5000