using transaction with multiple prepared statements
See original GitHub issueI found information about how to create prepared statements with a pool but didn’t find information about how to put multiple prepared statements in a Transaction. I created a database class first. This class manages the Connection and fires the query.
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
https://www.npmjs.com/package/mssql#prepared-statement
and about Transactions
https://www.npmjs.com/package/mssql#transaction
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
Issue Analytics
- State:
- Created 4 years ago
- Comments:7
So I finally got it working, this is my updated
run
function but would someone mind telling me if I can shorten this? I am not sure if this is the best way to do it@willmorgan I tried to reproduce my own question. First I created a database with a table called “integer” and a numeric column “value”. Then I created an empty Node/Typescript project with this code
So far so good. Now I want to run two INSERTs within a transaction but the second one passes in a string so I would expect an error and the first one gets rolled back. My updated
run
function:Now I get this error
and I’m not sure if my syntax is wrong.
I hope this clearifies my Problems 😃