I use node typescript with mssql library to insert data into tables in my Azure server. I create a global connection pool, init it in the constructor then connect to it from route service. However, it shows the error
ConnectionError: Connection is closed at ActionService.insertion", "...at new ActionService", "... at new AppDataServices".
I don't know where broke down my logical connection between the global pool and route service. My SQL query might be wrong, but the main thing is about connection to the database.
Below is my code:
app-data-services.ts (global connection pool):
import * as mssql from 'mssql';
import { AppConfig } from '../config';
import { ActionService } from './data-services';
import { Logger, LoggerFactory } from '../common';
export class AppDataServices {
private static readonly LOGGER: Logger = LoggerFactory.getLogger();
private db: any;
public actionService: ActionService;
constructor(private appConfig: AppConfig) {
this.initConnectionPool();
this.actionService = new ActionService(this.db, AppDataServices.LOGGER);
}
private initConnectionPool() {
this.db = new mssql.ConnectionPool({
user: this.appConfig.mssqlUsername,
password: this.appConfig.mssqlPassword,
server: this.appConfig.mssqlServer,
database: this.appConfig.mssqlDatabase,
// If you are on Microsoft Azure, you need this:
options: { encrypt: true }
}, (err: any) => {
if (err) AppDataServices.LOGGER.error('MSSQL error', err);
});
}
}
action-service.ts (route data service):
import * as mssql from 'mssql';
import { Logger, LoggerFactory } from '../../../common';
export class ActionService {
private static readonly LOGGER: Logger = LoggerFactory.getLogger();
constructor (private db: any, private logger: any) {
this.insertion();
}
insertion() {
const request = new mssql.Request(this.db);
request.query(
`
INSERT INTO dbo.action
(timestamp, result, description, request_endpoint, request_payload, response_status, response_payload, actualAmount, rule_id, lendbook_id)
SELECT t1.start, 'SUCCESS', NULL, '/lendbook/usd', NULL, '200', NULL, t1.originalAmount, t1.id, t2.id
FROM dbo.rule t1, dbo.lendbook t2
INNER JOIN t2.id = t1.id
`, (err, result) => {
if (err) {
console.error(err);
return;
}
return result.recordsets[0];
});
}
}
Related
I am creating a DB in my native Android code using SQLite. Now I want to access the same DB in Flutter, below is my code:
class DatabaseHelper
{
static final _dbName="abc.db";
static final _dbVersion=1;
DatabaseHelper._privateConstructor();
static final DatabaseHelper instance=DatabaseHelper._privateConstructor();
static Database _database;
Future<Database> get datatbase async
{
if(_database!=null) {
print(_database.path);
return _database;
}/* */
}
Future<List<Map<String,dynamic>>> getAllLogs()async
{
final Database db= await instance.datatbase;
return await db.query("calls_history");
}
Whenever I call getAllLogs in my Flutter Widget I get the error: calls_history doesn't exist.
However, when I run the same query on native, it returns me the result
On flutter side you can use sqflite plugin, this plugin is built on top of native SQLite so you don't need to do anything special just refer to the same database name in flutter.
In one of my flutter projects I have used native android to code to receive messages and save them in SQLite database and on the flutter side I have used same database using sqflite to display the contents of database.
Here is the flutter side code
import 'dart:async';
import 'package:path/path.dart';
import 'package:sqflite/sqflite.dart';
class SMSHelper {
Database? db;
Future open() async {
db = await openDatabase(
// by default path for database on the device is /data/data/<your app id>/databases/<your database file.db>
join(await getDatabasesPath(), 'ofs_sms_database.db'),
version: 1, onCreate: (Database db, int version) async {
await db.execute(
"CREATE TABLE smslogs(id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, employeeID TEXT, department TEXT, module TEXT, message TEXT, safeUnsafeStatus TEXT, contactNo Text, dateTime INTEGER)");
});
}
Future<void> insertSMS(SMSLog smsLog) async {
await db?.insert(
'smslogs',
smsLog.toMap(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
Future<List<SMSLog>> getAllSMS() async {
if (db == null) {
open();
}
final List<Map<String, dynamic>>? maps = await db?.query('smslogs');
// Convert the List<Map<String, dynamic> into a List<Dog>.
if (maps != null) {
return List.generate(maps.length, (i) {
return SMSLog(
employeeID: maps[i]['employeeID'],
department: maps[i]['department'],
module: maps[i]['module'],
message: maps[i]['message'],
safeUnsafeStatus: maps[i]['safeUnsafeStatus'],
contactNo: maps[i]['contactNo'],
dateTime: maps[i]['dateTime']);
});
} else {
return [];
}
}
Future close() async => db?.close();
}
class SMSLog {
final String employeeID;
final String department;
final String module;
final String message;
final String safeUnsafeStatus;
final String contactNo;
final int dateTime;
SMSLog(
{required this.employeeID,
required this.department,
required this.module,
required this.message,
required this.safeUnsafeStatus,
required this.contactNo,
required this.dateTime});
Map<String, dynamic> toMap() {
return {
'employeeID': employeeID,
'department': department,
'module': module,
'message': message,
'safeUnsafeStatus': safeUnsafeStatus,
'contactNo': contactNo,
'dateTime': dateTime
};
}
}
I am new to .Net Core - I need to add 2 connectionstrings (One for test db and one for live db), and want to connect to both - i.e. connect to live db and transfer data over to test db. Below is my appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=PC\\SQLEXPRESS;Database=[DB];User Id=[Username];Password=[Password];",
"MarkingManagerLIVEConnection": "Server=[IP];Database=[DB];User Id=[Username];Password=[Password]"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
I believe I need to register this:
private static void RegisterDatabase(IServiceCollection services, IConfiguration config)
{
services.AddDbContext<MarkingManagerDbContext>(options => options.UseSqlServer(config.GetConnectionString("DefaultConnection")));
services.AddDbContext<MarkingManagerDbContext>(liveoptions => liveoptions.UseSqlServer(config.GetConnectionString("MarkingManagerLIVEConnection")));
}
This is what is on the console apps Main:
static void Main(string[] args)
{
Console.Write("Register Services");
var services = new ServiceCollection();
RegisterServices.Register(services);
Console.WriteLine("=>Done");
_services = services.BuildServiceProvider();
Console.Write("DB Configuration");
var context = _services.GetRequiredService<MarkingManagerDbContext>();
var mmSeed = _services.GetRequiredService<MarkingManagerSeed>();
if (context.Database.EnsureCreated())
{
context.Database.Migrate();
var mmSeedTesk = mmSeed.Seed();
mmSeedTesk.Wait();
}
Console.WriteLine("=>Done");
Console.WriteLine("Press any key to end the process");
Console.ReadLine();
}
How do I make use of the "Live" Connectionstring ? Or am I missing something?
Thanks for any help!
I am currently writing a database class that receives a node http request and saves data into a db.
It uses MSSQL (yeah...), therefore I'm using node-mssql.
I created a class to manage DB access, code:
"use strict";
var config = require('../../config/mainConfigs');
const mssql = require('mssql');
class db {
constructor(){
this._pool = null;
}
get_pool(){
if (!this._pool) {
if (config.Logging.DB.type == 'mssql'){
const dbOptions = {
user: config.Logging.DB.user,
password: config.Logging.DB.password,
server: config.Logging.DB.mssql.server,
database: config.Logging.DB.mssql.database,
options: {
encrypt: config.Logging.DB.encrypt
}
};
this._pool = new mssql.ConnectionPool(dbOptions);
}
}
return this._pool;
}
insertHTTPRequest(req){
const pool = this.get_pool();
if (config.Logging.DB.type == 'mssql'){
if (pool._connected){
var request = new mssql.Request(pool);
var query = `INSERT INTO SD_LOG (
MODULE,
INSTANCE,
REMOTE_ADDR,
USERNAME,
USER_AGENT,
HTTP_METHOD,
HTTP_REQ_URL
) OUTPUT Inserted.ID_SD_LOG VALUES (
#module,
#instance,
#remote_addr,
#username,
#user_agent,
#http_method,
#http_req_url
)`;
request.input('module', 'tokenizer');
request.input('instance', config.Deployment.instance);
request.input('remote_addr', req.ip);
request.input('username', req.user.displayName);
request.input('user_agent', req.headers['user-agent']);
request.input('http_method', req.method);
request.input('http_req_url', req.url);
return request.query(query);
}else{
return pool.connect().then(() => {
var request = new mssql.Request(pool);
var query = `INSERT INTO SD_LOG (
MODULE,
INSTANCE,
REMOTE_ADDR,
USERNAME,
USER_AGENT,
HTTP_METHOD,
HTTP_REQ_URL
) OUTPUT Inserted.ID_SD_LOG VALUES (
#module,
#instance,
#remote_addr,
#username,
#user_agent,
#http_method,
#http_req_url
)`;
request.input('module', 'tokenizer');
request.input('instance', config.Deployment.instance);
request.input('remote_addr', req.ip);
request.input('username', req.user.displayName);
request.input('user_agent', req.headers['user-agent']);
request.input('http_method', req.method);
request.input('http_req_url', req.url);
request.query(query);
}
}
}
}
I am using a middleware in the routes to save the request into the DB, like this:
app.use(function(req, res, next){
//send req to DB, get ID_SD_LOG from DB, assign to req.id
db_instance.insertHTTPRequest(req).then((genid)=>{
req.id = genid;
next();
}).catch((err)=>{
combinedLogger.error(err);
res.send('Database is unavailable.');
res.end();
})
});
Thing is, I am getting an error, however, in console, the error is undefined. So I really can't figure out whats wrong. I can imagine it's the connect() method, as I tested logging in console static string in the db request and I don't them, which I assume it's not even accessing that part.
Any help?
Thanks!
Here is my node js code
app.get('/', function (req, res) {
var config = {
server: 'localhost\\SQLEXPRESS2008',
database: 'TestingDB'
};
// 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 userform', function (err, recordset) {
if (err) console.log(err)
// send records as a response
res.send(recordset);
console.log(recordset);
});
});
});
Please suggest me to connect sql and getting this error after running this in command prompt
Server is running.. on Port 8020
{ Error: Failed to connect to localhost:undefined in 15000ms
at Connection.tedious.once.err (D:\Nodejs\UsersCreate\node_modules\mssql\lib\tedious.js:216:17)
at Object.onceWrapper (events.js:293:19)
at emitOne (events.js:96:13)
at Connection.emit (events.js:191:7)
at Connection.connectTimeout (D:\Nodejs\UsersCreate\node_modules\tedious\lib\connection.js:795:12)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
code: 'ETIMEOUT',
originalError:
{ ConnectionError: Failed to connect to localhost:undefined in 15000ms
at ConnectionError (D:\Nodejs\UsersCreate\node_modules\tedious\lib\errors.js:12:12)
at Connection.connectTimeout (D:\Nodejs\UsersCreate\node_modules\tedious\lib\connection.js:795:28)
at ontimeout (timers.js:386:14)
at tryOnTimeout (timers.js:250:5)
at Timer.listOnTimeout (timers.js:214:5)
message: 'Failed to connect to localhost:undefined in 15000ms',
code: 'ETIMEOUT' },
name: 'ConnectionError' }
{ ConnectionError: Connection is closed.
at Request._query (D:\Nodejs\UsersCreate\node_modules\mssql\lib\base.js:1299:37)
at Request._query (D:\Nodejs\UsersCreate\node_modules\mssql\lib\tedious.js:497:11)
at Request.query (D:\Nodejs\UsersCreate\node_modules\mssql\lib\base.js:1242:12)
at D:\Nodejs\UsersCreate\app.js:118:17
at _poolCreate.then.catch.err (D:\Nodejs\UsersCreate\node_modules\mssql\lib\base.js:269:7) code: 'ECONNCLOSED', name: 'ConnectionError' }
undefined
This might help :
Start the "SQL SERVER BROWSER" Service in Windows services (I've configured it to start automatically)
allow SQL Server Express to accept remote connections over TCP/IP for port 1433 : http://support.webecs.com/kb/a868/how-do-i-configure-sql-server-express-to-allow-remote-tcp-ip-connections-on-port-1433.aspx
Finally restart 'SQL Server' and 'SQL Browser Agent' services
Installing mssql package I had a similiar problem and I got fixed addiyng an instance and database name to my config.
I thought it was better create an user on db.
After I need to handling the errors, addiyng try catch to my function that will connect in db and closing the connection if the function get an error.
All database connections are in a different file, so I export the modules to use in my application and if I need to use in other application just add a reference to that
let QueryDB = {
Query_SelectAll: 'SELECT [COLUMN] \
, [COLUMN] \
, [COLUMN] \
FROM [DATABASE].[dbo].[TABLE_NAME]',
Query_Delete: 'DELETE FROM [DATABASE].[dbo].[TABLE_NAME] WHERE COLUMN = '
};
I put all queries in an object to simplify the use for me.
let ConnectionString = {
user: 'YOUR_DBUSER',
password: '****',
server: '0.0.000.00',
options: {
instance: 'YOURINSTANCE',
database: 'DATABASE_NAME'
}
};
In the server property, I put the server IP, after add the options with instance and database name.
function SQL_Server(Query, ret) {
sql.close();
sql.connect(ConnectionString).then(() => {
console.log("Connected");
return request(Query, ret);
}).catch((error) => {
console.log("Connect error");
console.error(error);
sql.close();
});
}
function request(Query, ret) {
let returning = undefined;
let request = new sql.Request();
(request.query(Query).then((recordset) => {
sql.close();
returning = recordset.recordset;
}).catch((error) => {
console.error(error);
sql.close();
})).then(() => {
if (ret != undefined)
ret(returning);
console.log("Successful object return");
});
}
Those are my connect and request functions.
module.exports.SQL_Server = SQL_Server;
module.exports.QueryDB = QueryDB;
So I export the modules to use the functions.
An example of using:
let DataBase = require("./Connection_Query");
let FuncSql = DataBase.SQL_Server;
let SQL = DataBase.QueryDB;
APP.get(ProjectName + '/Home', (req, resp) => {
FuncSql(SQL.Query_SelectAll, (rec) => {
resp.render("Home", { YourObjects: rec });
});
});
Think that you use this answer to guide you.
you have to write the database instance in config.options.instanceName
var config = {
server: 'localhost\\SQLEXPRESS2008',
database: 'TestingDB'
};
instead:
const config = {
user: '...',
password: '...',
server: 'localhost',
database: 'TestingDB',
options: {
encrypt: false, // Use this if you're on Windows Azure
instanceName: 'SQLEXPRESS2008'
}
};
Pls How can I access sqlite database on the webserver in codename one? I can only use database API to access database on the device. In order to access this on the webserver I think is quite different thing. Pls I need a snippet code on this. Thanks
Use the code below, not tested and you may have to adjust it to suite your need. Leave a comment if there's an issue:
ConnectionRequest req = new ConnectionRequest() {
#Override
protected void handleException(Exception ex) {
//handle error
}
};
req.setUrl(YourURL);
req.setPost(true);
req.setHttpMethod("POST"); //Change to GET if necessary
req.setDuplicateSupported(true);
req.addArgument("argumentToSendThroughPostOrGet1", "value1");
req.addArgument("argumentToSendThroughPostOrGet2", "value2");
NetworkManager.getInstance().addToQueueAndWait(req);
if (req.getResponseCode() == 200) {
Map<String, Object> out = new HashMap<>();
Display.getInstance().invokeAndBlock(() -> {
JSONParser p = new JSONParser();
try (InputStreamReader r = new InputStreamReader(new ByteArrayInputStream(req.getResponseData()))) {
out.putAll(p.parseJSON(r));
} catch (IOException ex) {
//handle error
}
});
if (!out.isEmpty()) {
List<Map<String, Object>> responses = (List<Map<String, Object>>) out.get("response");
for (Object response : responses) {
Map res = (Map) response;
System.out.println(res.get("key"));
}
} else {
//handle error
}
} else {
//handle error
}
TEST JSON RESPONSE:
{
"response": [
{
"key": "I was returned",
}
]
}
EDIT:
To pass data from TextField:
req.addArgument("argumentToSendThroughPostOrGet1", myTextField.getText());
Based on your comment, you can read those arguments in PHP as simple as below:
$var1 = $_POST["argumentToSendThroughPostOrGet1"];
$var1 = $_GET["argumentToSendThroughPostOrGet1"]; // if GET method is used in Codename One
//Or use $_REQUEST which supports both methods but not advisable to be used for production
...
And you can use those variables in your php code normally.
Example of Usage with MySql Query:
class Connection {
function connect() {
$mysqli = mysqli_init();
$mysqli->real_connect("localhost", "username", "password", "databaseName") or die('Could not connect to database!');
$mysqli->query("SET NAMES 'UTF8'");
return $mysqli;
}
function close() {
mysqli_close($this->connect);
}
}
$connection = new Connection();
$mysqli = $connection->connect();
$mysqli->query("SELECT * FROM MyTable WHERE ColumnName LIKE '%$var1%' ORDER BY PrimaryKeyId ASC LIMIT 100");