Skip to content

Commit 1130296

Browse files
committed
Addition - Execute Transaction
1 parent 0bd2ddf commit 1130296

File tree

7 files changed

+329
-2
lines changed

7 files changed

+329
-2
lines changed

QueryDB/DBContext.cs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,57 @@ public int ExecuteCommand(string sqlStatement)
190190
return -1;
191191
}
192192

193+
/// <summary>
194+
/// Executes multiple SQL statements within a transaction, ensuring that all statements are executed together.
195+
/// </summary>
196+
/// <param name="sqlStatements">A list of SQL statements to execute.</param>
197+
/// <returns>
198+
/// Returns <c>true</c> if all statements are executed successfully and the transaction is committed;
199+
/// <c>false</c> if any statement fails and the transaction is rolled back.
200+
/// </returns>
201+
public bool ExecuteTransaction(List<string> sqlStatements)
202+
{
203+
foreach(var sqlStatement in sqlStatements)
204+
{
205+
if (Regex.IsMatch(sqlStatement, "^\\s*SELECT\\s+.*", RegexOptions.IgnoreCase | RegexOptions.Singleline, TimeSpan.FromSeconds(5)))
206+
throw new QueryDBException(QueryDBExceptions.ErrorMessage.UnsupportedSelectExecuteTransaction,
207+
QueryDBExceptions.ErrorType.UnsupportedCommand, QueryDBExceptions.AdditionalInfo.UnsupportedSelectExecuteTransaction);
208+
}
209+
if (Database.Equals(DB.MSSQL))
210+
{
211+
using (var msSqlDBConnection = GetSqlServerConnection())
212+
{
213+
var _systemAdapter = new MSSQL.Adapter();
214+
return _systemAdapter.ExecuteTransaction(sqlStatements, msSqlDBConnection.SqlConnection);
215+
}
216+
}
217+
else if (Database.Equals(DB.MySQL))
218+
{
219+
using (var mySqlDBConnection = GetMySqlConnection())
220+
{
221+
var _systemAdapter = new MySQL.Adapter();
222+
return _systemAdapter.ExecuteTransaction(sqlStatements, mySqlDBConnection.MySqlConnection);
223+
}
224+
}
225+
else if (Database.Equals(DB.Oracle))
226+
{
227+
using (var oracleDBConnection = GetOracleConnection())
228+
{
229+
var _systemAdapter = new Oracle.Adapter();
230+
return _systemAdapter.ExecuteTransaction(sqlStatements, oracleDBConnection.OracleConnection);
231+
}
232+
}
233+
else if (Database.Equals(DB.PostgreSQL))
234+
{
235+
using (var postgreSqlDBConnection = GetPostgreSqlConnection())
236+
{
237+
var _systemAdapter = new PostgreSQL.Adapter();
238+
return _systemAdapter.ExecuteTransaction(sqlStatements, postgreSqlDBConnection.PostgreSQLConnection);
239+
}
240+
}
241+
return false;
242+
}
243+
193244
/// <summary>
194245
/// Gets 'SQL Server' connection.
195246
/// </summary>

QueryDB/Exceptions/QueryDBException.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,14 @@ internal static class ErrorType
6262
internal static class ErrorMessage
6363
{
6464
/// <summary>
65-
/// Error message indicating that SELECT queries are not supported.
65+
/// Error message indicating that SELECT queries are not supported in 'ExecuteCommand'.
6666
/// </summary>
6767
internal static readonly string UnsupportedSelectExecuteCommand = "SELECT queries are not supported here.";
68+
69+
/// <summary>
70+
/// Error message indicating that SELECT queries are not supported in 'ExecuteTransaction'.
71+
/// </summary>
72+
internal static readonly string UnsupportedSelectExecuteTransaction = "SELECT queries are not supported here.";
6873
}
6974

7075
/// <summary>
@@ -76,6 +81,11 @@ internal static class AdditionalInfo
7681
/// Additional information about unsupported SELECT queries in 'ExecuteCommand'.
7782
/// </summary>
7883
internal static readonly string UnsupportedSelectExecuteCommand = "'ExecuteCommand' doesn't support SELECT queries.";
84+
85+
/// <summary>
86+
/// Additional information about unsupported SELECT queries in 'ExecuteTransaction'.
87+
/// </summary>
88+
internal static readonly string UnsupportedSelectExecuteTransaction = "'ExecuteTransaction' doesn't support SELECT queries.";
7989
}
8090
}
8191
}

QueryDB/IDBContext.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,15 @@ interface IDBContext
3131
/// <param name="sqlStatement">SQL statement as command.</param>
3232
/// <returns>The number of rows affected.</returns>
3333
int ExecuteCommand(string sqlStatement);
34+
35+
/// <summary>
36+
/// Executes multiple SQL statements within a transaction, ensuring that all statements are executed together.
37+
/// </summary>
38+
/// <param name="sqlStatements">A list of SQL statements to execute.</param>
39+
/// <returns>
40+
/// Returns <c>true</c> if all statements are executed successfully and the transaction is committed;
41+
/// <c>false</c> if any statement fails and the transaction is rolled back.
42+
/// </returns>
43+
bool ExecuteTransaction(List<string> sqlStatements);
3444
}
3545
}

QueryDB/MSSQL/Adapter.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,33 @@ internal SqlCommand GetSqlCommand(string cmdText, SqlConnection connection, Comm
4242
return sqlCommand;
4343
}
4444

45+
/// <summary>
46+
/// Creates and returns a new SQL command associated with the specified connection and transaction.
47+
/// </summary>
48+
/// <param name="cmdText">The SQL command text to execute.</param>
49+
/// <param name="connection">The SQL database connection.</param>
50+
/// <param name="transaction">The SQL transaction within which the command should be executed.</param>
51+
/// <returns>A new <see cref="SqlCommand"/> instance configured with the provided connection and transaction.</returns>
52+
internal SqlCommand GetSqlCommand(string cmdText, SqlConnection connection, SqlTransaction transaction)
53+
{
54+
if (connection.State != ConnectionState.Open)
55+
connection.Open();
56+
var sqlCommand = new SqlCommand(cmdText, connection, transaction);
57+
return sqlCommand;
58+
}
59+
60+
/// <summary>
61+
/// Initiates and returns a new SQL transaction for the specified database connection.
62+
/// </summary>
63+
/// <param name="connection">The SQL database connection.</param>
64+
/// <returns>A new <see cref="SqlTransaction"/> associated with the provided connection.</returns>
65+
internal SqlTransaction GetSqlTransaction(SqlConnection connection)
66+
{
67+
connection.Open();
68+
var sqlTransaction = connection.BeginTransaction();
69+
return sqlTransaction;
70+
}
71+
4572
/// <summary>
4673
/// Retrieves records for 'Select' queries from the database.
4774
/// Converts column names to keys holding values, with multiple database rows returned into a list.
@@ -113,5 +140,43 @@ internal int ExecuteCommand(string sqlStatement, SqlConnection connection)
113140
return sqlCommand.ExecuteNonQuery();
114141
}
115142
}
143+
144+
/// <summary>
145+
/// Executes multiple SQL statements within a transaction to ensure atomicity.
146+
/// </summary>
147+
/// <param name="sqlStatements">A list of SQL statements to execute.</param>
148+
/// <param name="connection">The SQL database connection.</param>
149+
/// <returns>
150+
/// Returns <c>true</c> if the transaction is committed successfully;
151+
/// otherwise, <c>false</c> if an error occurs and the transaction is rolled back.
152+
/// </returns>
153+
/// <exception cref="Exception">
154+
/// Logs and handles exceptions if any SQL command execution fails.
155+
/// </exception>
156+
157+
internal bool ExecuteTransaction(List<string> sqlStatements, SqlConnection connection)
158+
{
159+
using (SqlTransaction transaction = GetSqlTransaction(connection))
160+
{
161+
try
162+
{
163+
foreach (var sqlStatement in sqlStatements)
164+
{
165+
using (var sqlCommand = GetSqlCommand(sqlStatement, connection, transaction))
166+
{
167+
sqlCommand.ExecuteNonQuery();
168+
}
169+
}
170+
transaction.Commit();
171+
return true;
172+
}
173+
catch (Exception ex)
174+
{
175+
transaction.Rollback();
176+
Console.WriteLine($"Transaction rolled back due to error: {ex.Message}");
177+
return false;
178+
}
179+
}
180+
}
116181
}
117182
}

QueryDB/MySQL/Adapter.cs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,33 @@ internal MySqlCommand GetMySqlCommand(string cmdText, MySqlConnection connection
4242
return sqlCommand;
4343
}
4444

45+
/// <summary>
46+
/// Creates and returns a new MySQL command associated with the specified connection and transaction.
47+
/// </summary>
48+
/// <param name="cmdText">The SQL command text to execute.</param>
49+
/// <param name="connection">The MySQL database connection.</param>
50+
/// <param name="transaction">The MySQL transaction within which the command should be executed.</param>
51+
/// <returns>A new <see cref="MySqlCommand"/> instance configured with the provided connection and transaction.</returns>
52+
internal MySqlCommand GetMySqlCommand(string cmdText, MySqlConnection connection, MySqlTransaction transaction)
53+
{
54+
if (connection.State != ConnectionState.Open)
55+
connection.Open();
56+
var sqlCommand = new MySqlCommand(cmdText, connection, transaction);
57+
return sqlCommand;
58+
}
59+
60+
/// <summary>
61+
/// Initiates and returns a new MySQL transaction for the given database connection.
62+
/// </summary>
63+
/// <param name="connection">The MySQL database connection.</param>
64+
/// <returns>A new <see cref="MySqlTransaction"/> associated with the provided connection.</returns>
65+
internal MySqlTransaction GetMySqlTransaction(MySqlConnection connection)
66+
{
67+
connection.Open();
68+
var mySqlTransaction = connection.BeginTransaction();
69+
return mySqlTransaction;
70+
}
71+
4572
/// <summary>
4673
/// Retrieves records for 'Select' queries from the database.
4774
/// Converts column names to keys holding values, with multiple database rows returned into a list.
@@ -113,5 +140,42 @@ internal int ExecuteCommand(string sqlStatement, MySqlConnection connection)
113140
return sqlCommand.ExecuteNonQuery();
114141
}
115142
}
143+
144+
/// <summary>
145+
/// Executes multiple SQL statements within a MySQL transaction to ensure atomicity.
146+
/// </summary>
147+
/// <param name="sqlStatements">A list of SQL statements to execute.</param>
148+
/// <param name="connection">The MySQL database connection.</param>
149+
/// <returns>
150+
/// Returns <c>true</c> if the transaction is committed successfully;
151+
/// otherwise, <c>false</c> if an error occurs and the transaction is rolled back.
152+
/// </returns>
153+
/// <exception cref="Exception">
154+
/// Logs and handles exceptions if any SQL command execution fails.
155+
/// </exception>
156+
internal bool ExecuteTransaction(List<string> sqlStatements, MySqlConnection connection)
157+
{
158+
using (MySqlTransaction transaction = GetMySqlTransaction(connection))
159+
{
160+
try
161+
{
162+
foreach (var sqlStatement in sqlStatements)
163+
{
164+
using (var sqlCommand = GetMySqlCommand(sqlStatement, connection, transaction))
165+
{
166+
sqlCommand.ExecuteNonQuery();
167+
}
168+
}
169+
transaction.Commit();
170+
return true;
171+
}
172+
catch (Exception ex)
173+
{
174+
transaction.Rollback();
175+
Console.WriteLine($"Transaction rolled back due to error: {ex.Message}");
176+
return false;
177+
}
178+
}
179+
}
116180
}
117181
}

QueryDB/Oracle/Adapter.cs

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,36 @@ internal OracleDataReader GetOracleReader(string cmdText, OracleConnection conne
3737
/// <returns>A configured <see cref="OracleCommand"/> instance.</returns>
3838
internal OracleCommand GetOracleCommand(string cmdText, OracleConnection connection, CommandType commandType)
3939
{
40-
connection.Open();
4140
var sqlCommand = new OracleCommand(cmdText, connection) { CommandType = commandType };
4241
return sqlCommand;
4342
}
4443

44+
/// <summary>
45+
/// Creates and returns a new Oracle command associated with the specified connection.
46+
/// </summary>
47+
/// <param name="cmdText">The SQL command text to execute.</param>
48+
/// <param name="connection">The Oracle database connection.</param>
49+
/// <returns>A new <see cref="OracleCommand"/> instance configured with the provided connection.</returns>
50+
internal OracleCommand GetOracleCommand(string cmdText, OracleConnection connection)
51+
{
52+
if (connection.State != ConnectionState.Open)
53+
connection.Open();
54+
var sqlCommand = new OracleCommand(cmdText, connection);
55+
return sqlCommand;
56+
}
57+
58+
/// <summary>
59+
/// Initiates and returns a new Oracle transaction for the specified database connection.
60+
/// </summary>
61+
/// <param name="connection">The Oracle database connection.</param>
62+
/// <returns>A new <see cref="OracleTransaction"/> associated with the provided connection.</returns>
63+
internal OracleTransaction GetOracleTransaction(OracleConnection connection)
64+
{
65+
connection.Open();
66+
var oracleTransaction = connection.BeginTransaction();
67+
return oracleTransaction;
68+
}
69+
4570
/// <summary>
4671
/// Retrieves records for 'Select' queries from the database.
4772
/// Converts column names to keys holding values, with multiple database rows returned into a list.
@@ -120,5 +145,43 @@ internal int ExecuteCommand(string sqlStatement, OracleConnection connection)
120145
return sqlCommand.ExecuteNonQuery();
121146
}
122147
}
148+
149+
/// <summary>
150+
/// Executes multiple SQL statements within an Oracle transaction to ensure atomicity.
151+
/// </summary>
152+
/// <param name="sqlStatements">A list of SQL statements to execute.</param>
153+
/// <param name="connection">The Oracle database connection.</param>
154+
/// <returns>
155+
/// Returns <c>true</c> if the transaction is committed successfully;
156+
/// otherwise, <c>false</c> if an error occurs and the transaction is rolled back.
157+
/// </returns>
158+
/// <exception cref="Exception">
159+
/// Logs and handles exceptions if any SQL command execution fails.
160+
/// </exception>
161+
internal bool ExecuteTransaction(List<string> sqlStatements, OracleConnection connection)
162+
{
163+
using (OracleTransaction transaction = GetOracleTransaction(connection))
164+
{
165+
try
166+
{
167+
foreach (var sqlStatement in sqlStatements)
168+
{
169+
using (var sqlCommand = GetOracleCommand(sqlStatement, connection))
170+
{
171+
sqlCommand.Transaction = transaction;
172+
sqlCommand.ExecuteNonQuery();
173+
}
174+
}
175+
transaction.Commit();
176+
return true;
177+
}
178+
catch (Exception ex)
179+
{
180+
transaction.Rollback();
181+
Console.WriteLine($"Transaction rolled back due to error: {ex.Message}");
182+
return false;
183+
}
184+
}
185+
}
123186
}
124187
}

0 commit comments

Comments
 (0)