namespace LaaProduction.SQL { using LaaProduction.SQL.Interfaces; using System; using System.Collections.Generic; using System.Data.SqlClient; using System.Linq; /// /// A wrapper class around the . /// Exposes , and classes /// in a fluent manner, all exposed methods can be chained in a single C# query. /// public class SQLConnection : ISQLConnection { private readonly string connectionString; private readonly Action errorCallback; /// /// When is null, white space or is not a valid connection string exception is thrown. /// /// - SQL connection string. public SQLConnection(string connectionString) { connectionString.ThrowIfNullOrWhiteSpace(nameof(connectionString)); var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString); this.connectionString = connectionStringBuilder.ToString(); } /// /// When is null, white space or is not a valid connection string exception is thrown. /// Additionaly accepts for error handling. /// Whenever the sql query throws error on execution, this will be passesd within the callback. /// /// - SQL connection string. /// - error handler for SQL execution errors. public SQLConnection(string connectionString, Action errorCallback = null) : this(connectionString) => this.errorCallback = errorCallback; /// /// Creates a wrapper that accepts a SQL query string. /// /// - SQL query string /// - that exposes basic functionalities from the . public ISQLCommand CreateCommand(string commandText) => new SQLCommand(this, commandText); /// /// Static method that creates a client with given connection string. /// /// - SQL connection string. /// public static ISQLConnection CreateSQLConnection(string connectionString) => new SQLConnection(connectionString); /// /// Static method that creates a client with given connection string and error callback that receives all error messages. /// /// - SQL connection string. /// - error handler for SQL execution errors. /// public static ISQLConnection CreateSQLConnection(string connectionString, Action errorCallback = null) => new SQLConnection(connectionString, errorCallback); /// /// Internal method called from . /// Like in a performs INSERT, UPDATE, DELETE queries and returns the number of rows affected. /// /// - SQL query string /// - the number of rows affected. internal int ExecuteNonQuery(SQLCommand command) { command.ThrowIfNull(nameof(command)); var rowsAffected = 0; using (var sqlConnection = new SqlConnection(this.connectionString)) { sqlConnection.OpenWithErrorHandling(this.errorCallback); using (var sqlCommand = sqlConnection.CreateCommand()) { sqlCommand.CommandText = command.CommandText; sqlCommand.Parameters.AddRange(command.Parameters); rowsAffected = sqlCommand.ExecuteNonQuery(); sqlCommand.Parameters.Clear(); } } return rowsAffected; } /// /// Internal method called from . /// Like in a performs SELECT queries and returns a enumerable of the results readed. /// /// Is the type that returns the /// - SQL query string /// Expression that reads specified data from the . /// internal IEnumerable ExecuteReader(SQLCommand command, Func expression) { command.ThrowIfNull(nameof(command)); expression.ThrowIfNull(nameof(expression)); using (var sqlConnection = new SqlConnection(this.connectionString)) { sqlConnection.OpenWithErrorHandling(this.errorCallback); using (var sqlCommand = sqlConnection.CreateCommand()) { sqlCommand.CommandText = command.CommandText; sqlCommand.Parameters.AddRange(command.Parameters); using (SQLReader sqlReader = sqlCommand.ExecuteReader()) { sqlCommand.Parameters.Clear(); while (sqlReader.Read()) { yield return expression(sqlReader); } } } } } /// /// Internal method called from . /// Like in a performs SELECT, READ, UPDATE, DELETE queries and returns first column from the first row from the result. /// /// From user specified. /// - SQL query string /// Expression that reads specified data from the . /// internal T ExecuteScalar(SQLCommand command, Func expression) { command.ThrowIfNull(nameof(command)); expression.ThrowIfNull(nameof(expression)); var scalarResult = default(T); using (var sqlConnection = new SqlConnection(this.connectionString)) { sqlConnection.OpenWithErrorHandling(this.errorCallback); using (var sqlCommand = sqlConnection.CreateCommand()) { sqlCommand.CommandText = command.CommandText; sqlCommand.Parameters.AddRange(command.Parameters); var scalarObject = sqlCommand.ExecuteScalar(); sqlCommand.Parameters.Clear(); if (scalarObject is T scalarValue) { scalarResult = scalarValue; } } } return scalarResult; } /// /// Is same like but returns only the first data row. /// /// From user specified. /// - SQL query string /// Expression that reads specified data from the . /// internal T FirstOrDefault(SQLCommand command, Func expression) => this .ExecuteReader(command, expression) .FirstOrDefault(); } }