I want to create an Express REST API and will use MSSQL for the database part. I use the mssql module and created a database class first
import sql, { ConnectionPool, PreparedStatement, IProcedureResult } from 'mssql';
import { injectable } from 'inversify';
import { IDatabase } from './IDatabase';
import { InternalServerErrorException } from '../../interfaceAdapters/httpExceptions/InternalServerErrorException';
import * as databaseConfig from '../../config/DatabaseConfig';
@injectable()
export class Database implements IDatabase {
public connectionPool: ConnectionPool;
constructor() {
this.connectionPool = new sql.ConnectionPool(databaseConfig);
}
public connect = async (): Promise<void> => {
try {
await this.connectionPool.connect();
} catch (error) {
throw error;
}
}
public query = async (builder: Function) : Promise<IProcedureResult<any>> => {
try {
const rawStatement: PreparedStatement = new sql.PreparedStatement(this.connectionPool);
const queryInfo: any = builder(rawStatement);
const { preparedStatement, queryString, queryParams = {} }: { preparedStatement: PreparedStatement, queryString: string, queryParams: object } = queryInfo;
await preparedStatement.prepare(queryString);
const queryResult: IProcedureResult<any> = await preparedStatement.execute(queryParams);
await preparedStatement.unprepare();
return queryResult;
} catch (error) {
throw new InternalServerErrorException(error.message);
}
}
}
As you can see I created a query
function with a builder
parameter. I have multiple queries from multiple classes and don't want to write the same code over and over again so I pass in only the things that differ from query to query. A basic example would be my fetchUserById
example
public fetchUserById = async (params: any[]): Promise<QueryResult> => {
try {
const queryResult: IProcedureResult<any> = await this.database.query((preparedStatement: PreparedStatement) => {
preparedStatement.input('userId', sql.Numeric);
const queryString: string = `
SELECT *
FROM users
WHERE id = @userId
`;
const queryParams: object = {
userId: params[0]
};
return {
preparedStatement,
queryString,
queryParams,
};
});
return new QueryResult(queryResult.recordset, queryResult.rowsAffected.length);
} catch (error) {
throw error;
}
}
The database provides the preparedStatement
object and the query passes back the updated statement, the query string and the parameters.
This code works fine but doesn't provide the possibility for transactional queries.
I found some information about prepared statements here and about transactions here but don't know how to execute transactional queries using prepared statements.
Would someone mind explaining how to use the mssql module to provide the possibility using prepared statements within transactions? My database query
function should provide a functionality giving access to write something like this in my query file
- begin transaction
- run insertQuery one
- run insertQuery two
- end transaction
from transaction for prepared statements using Node mssql
No comments:
Post a Comment