node-mssql 具有单个连接的多个准备好的语句
node-mssql multiple prepared statements with single connection
我对这个图书馆很反感。我试图设置一个单例中介 class 来启动连接,然后通过静态方法共享该连接。我的问题是我很难设置东西,以便在 运行 查询时连接已经打开,但不必再次重新打开它。由于连接的打开当然是异步的,我不能将所有内容都放在打开回调中,因为那完全是在另一个时间的其他地方发生的……我唯一能做的就是分享 mssql.Connection
,它是 "connecting": true
。这就是为什么我不在 Database.connect()
中执行 connection.connect()
如何打开连接并在知道连接打开的情况下继续准备语句和运行查询?
我的问题是,每当我的代码从第二次开始到达 connection.connect()
时,它会遇到错误 EALREADYCONNECTING
,因为连接已经正在打开。
我考虑过做某种 Promise 查询池,一旦连接本身通过 Promise 得到解决,就可以解决,但现在我的大脑很困惑!
let mssql = require('mssql');
let fs = require('fs');
class Database
{
static connect(username, password, server, database)
{
if (Database.connection !== null) {
return Database.connection;
}
let storedUsername = null;
let storedPassword = null;
let storedServer = null;
let storedDatabase = null;
try {
fs.accessSync(__dirname + '/../../config.json');
let data = fs.readFileSync(__dirname + '/../../config.json')
data = JSON.parse(data);
storedUsername = data.sql.username;
storedPassword = data.sql.password;
storedServer = data.sql.server;
storedDatabase = data.sql.database;
} catch (e) {
// Do nothing
}
var config = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(config);
return Database.connection;
}
static getConnection()
{
if (Database.connection === null) {
try {
Database.connect();
} catch (e) {
throw new Error('Database.getConnection: Database not connected.');
}
}
return Database.connection;
}
static getInstance()
{
return mssql;
}
static query(query, fields)
{
if (typeof query !== 'string' || typeof fields !== 'object') {
throw new Error("Invalid parameters");
}
let db = Database.getInstance();
let connection = Database.getConnection();
let ps = new db.PreparedStatement(connection);
let values = {};
fields.forEach(function(current, index) {
ps.input(current.name, current.type);
values[current.name] = current.value;
});
connection.connect(function(err) {
if (err) {
throw err;
}
ps.prepare(query, function(err) {
if (err) {
throw new Error(err);
}
ps.execute(values, function(err, recordset, affected) {
if (err) {
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
throw new Error(err);
}
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
});
});
});
}
}
Database.connection = null;
module.exports = Database;
不太确定您遵循的模式是否对 node.js 有用,它对非事件驱动的编程非常有用,但要使其与 node.js 一起使用,您需要按照建议进行循环在评论中。那只是违背了目的。
第二点是,您实质上是在为 mssql class 创建一个包装器,这增加了另一层复杂性,可能会引入错误并使维护变得更加困难。下一个使用此代码的人会知道 mssql,但不会知道您正在创建的 class 以及您必须实施的解决方法才能使其工作。
使用一个连接的最佳方式是将您的所有查询放在连接上的回调中
try {
fs.accessSync(__dirname + '/../../config.json');
let data = fs.readFileSync(__dirname + '/../../config.json')
data = JSON.parse(data);
storedUsername = data.sql.username;
storedPassword = data.sql.password;
storedServer = data.sql.server;
storedDatabase = data.sql.database;
} catch (e) {
// Actually you must do something here. If nothing else
// at least log it so that later on you are not left wondering
// why nothing seems to work.
}
var config = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(config);
connection.connect(function(err) {
// do everything here
});
module documentation中并没有真正提到,但是你可以监听连接事件。因此,如果您想保持结构井井有条并避免重复,您可以在 Connection
上监听 connect
事件。这对我来说似乎是完美的答案。
let mssql = require('mssql');
let fs = require('fs');
class Database
{
static connect(username, password, server, database)
{
if (Database.connection !== null) {
return Database.connection;
}
let storedUsername = null;
let storedPassword = null;
let storedServer = null;
let storedDatabase = null;
try {
fs.accessSync(__dirname + '/../../config.js');
let config = require(__dirname + '/../../config')
storedUsername = config.sql.username;
storedPassword = config.sql.password;
storedServer = config.sql.server;
storedDatabase = config.sql.database;
} catch (err) {
console.log(err);
}
let configuration = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(configuration);
Database.connection.connect();
}
static disconnect()
{
Database.connection.close();
}
static getConnection()
{
if (Database.connection === null) {
try {
Database.connect();
} catch (e) {
throw new Error('Database.getConnection: Database not connected.');
}
}
return Database.connection;
}
static getInstance()
{
return mssql;
}
static query(query, fields)
{
if (typeof query !== 'string' || typeof fields !== 'object') {
throw new Error("Invalid parameters");
}
let db = Database.getInstance();
let connection = Database.getConnection();
let ps = new db.PreparedStatement(connection);
let values = {};
fields.forEach(function(current, index) {
ps.input(current.name, current.type);
values[current.name] = current.value;
});
connection.on('connect', function(err) {
if (err) {
throw err;
}
ps.prepare(query, function(err) {
if (err) {
throw new Error(err);
}
ps.execute(values, function(err, recordset, affected) {
if (err) {
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
throw new Error(err);
}
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
});
});
});
}
}
Database.connection = null;
module.exports = Database;
现在也许我应该 Promise-fy query()
方法中的那些回调。
我对这个图书馆很反感。我试图设置一个单例中介 class 来启动连接,然后通过静态方法共享该连接。我的问题是我很难设置东西,以便在 运行 查询时连接已经打开,但不必再次重新打开它。由于连接的打开当然是异步的,我不能将所有内容都放在打开回调中,因为那完全是在另一个时间的其他地方发生的……我唯一能做的就是分享 mssql.Connection
,它是 "connecting": true
。这就是为什么我不在 Database.connect()
connection.connect()
如何打开连接并在知道连接打开的情况下继续准备语句和运行查询?
我的问题是,每当我的代码从第二次开始到达 connection.connect()
时,它会遇到错误 EALREADYCONNECTING
,因为连接已经正在打开。
我考虑过做某种 Promise 查询池,一旦连接本身通过 Promise 得到解决,就可以解决,但现在我的大脑很困惑!
let mssql = require('mssql');
let fs = require('fs');
class Database
{
static connect(username, password, server, database)
{
if (Database.connection !== null) {
return Database.connection;
}
let storedUsername = null;
let storedPassword = null;
let storedServer = null;
let storedDatabase = null;
try {
fs.accessSync(__dirname + '/../../config.json');
let data = fs.readFileSync(__dirname + '/../../config.json')
data = JSON.parse(data);
storedUsername = data.sql.username;
storedPassword = data.sql.password;
storedServer = data.sql.server;
storedDatabase = data.sql.database;
} catch (e) {
// Do nothing
}
var config = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(config);
return Database.connection;
}
static getConnection()
{
if (Database.connection === null) {
try {
Database.connect();
} catch (e) {
throw new Error('Database.getConnection: Database not connected.');
}
}
return Database.connection;
}
static getInstance()
{
return mssql;
}
static query(query, fields)
{
if (typeof query !== 'string' || typeof fields !== 'object') {
throw new Error("Invalid parameters");
}
let db = Database.getInstance();
let connection = Database.getConnection();
let ps = new db.PreparedStatement(connection);
let values = {};
fields.forEach(function(current, index) {
ps.input(current.name, current.type);
values[current.name] = current.value;
});
connection.connect(function(err) {
if (err) {
throw err;
}
ps.prepare(query, function(err) {
if (err) {
throw new Error(err);
}
ps.execute(values, function(err, recordset, affected) {
if (err) {
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
throw new Error(err);
}
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
});
});
});
}
}
Database.connection = null;
module.exports = Database;
不太确定您遵循的模式是否对 node.js 有用,它对非事件驱动的编程非常有用,但要使其与 node.js 一起使用,您需要按照建议进行循环在评论中。那只是违背了目的。
第二点是,您实质上是在为 mssql class 创建一个包装器,这增加了另一层复杂性,可能会引入错误并使维护变得更加困难。下一个使用此代码的人会知道 mssql,但不会知道您正在创建的 class 以及您必须实施的解决方法才能使其工作。
使用一个连接的最佳方式是将您的所有查询放在连接上的回调中
try {
fs.accessSync(__dirname + '/../../config.json');
let data = fs.readFileSync(__dirname + '/../../config.json')
data = JSON.parse(data);
storedUsername = data.sql.username;
storedPassword = data.sql.password;
storedServer = data.sql.server;
storedDatabase = data.sql.database;
} catch (e) {
// Actually you must do something here. If nothing else
// at least log it so that later on you are not left wondering
// why nothing seems to work.
}
var config = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(config);
connection.connect(function(err) {
// do everything here
});
module documentation中并没有真正提到,但是你可以监听连接事件。因此,如果您想保持结构井井有条并避免重复,您可以在 Connection
上监听 connect
事件。这对我来说似乎是完美的答案。
let mssql = require('mssql');
let fs = require('fs');
class Database
{
static connect(username, password, server, database)
{
if (Database.connection !== null) {
return Database.connection;
}
let storedUsername = null;
let storedPassword = null;
let storedServer = null;
let storedDatabase = null;
try {
fs.accessSync(__dirname + '/../../config.js');
let config = require(__dirname + '/../../config')
storedUsername = config.sql.username;
storedPassword = config.sql.password;
storedServer = config.sql.server;
storedDatabase = config.sql.database;
} catch (err) {
console.log(err);
}
let configuration = {
user: username || storedUsername || '',
password: password || storedPassword || '',
server: server || storedServer || 'localhost',
database: database || storedDatabase || '',
}
Database.connection = new mssql.Connection(configuration);
Database.connection.connect();
}
static disconnect()
{
Database.connection.close();
}
static getConnection()
{
if (Database.connection === null) {
try {
Database.connect();
} catch (e) {
throw new Error('Database.getConnection: Database not connected.');
}
}
return Database.connection;
}
static getInstance()
{
return mssql;
}
static query(query, fields)
{
if (typeof query !== 'string' || typeof fields !== 'object') {
throw new Error("Invalid parameters");
}
let db = Database.getInstance();
let connection = Database.getConnection();
let ps = new db.PreparedStatement(connection);
let values = {};
fields.forEach(function(current, index) {
ps.input(current.name, current.type);
values[current.name] = current.value;
});
connection.on('connect', function(err) {
if (err) {
throw err;
}
ps.prepare(query, function(err) {
if (err) {
throw new Error(err);
}
ps.execute(values, function(err, recordset, affected) {
if (err) {
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
throw new Error(err);
}
ps.unprepare(function(err) {
if (err) {
throw new Error(err);
}
});
});
});
});
}
}
Database.connection = null;
module.exports = Database;
现在也许我应该 Promise-fy query()
方法中的那些回调。