using System.Data; using System.Data.Common; using Elsa.Sql.Models; namespace Elsa.Sql.Client; public abstract class BaseSqlClient : ISqlClient { /// /// The connection string used to connect with the database. /// protected readonly string _connectionString; /// /// The marker used when injecting parameters into a query. /// Default: "@" /// public virtual string ParameterMarker { get; set; } = "@"; /// /// The text following the ParameterMarker when injecting parameters into a query. /// Default: "param" /// public virtual string ParameterText { get; set; } = "p"; /// /// Set to true to add a counter to the end of the parameter string. /// Default: true /// public virtual bool IncrementParameter { get; set; } = true; /// /// Create a connection using the client specific connection. /// /// protected abstract DbConnection CreateConnection(); /// /// Create a command using the client specific connection. /// /// /// /// protected abstract DbCommand CreateCommand(string query, DbConnection connection); /// /// /// /// protected BaseSqlClient(string connectionString) => _connectionString = connectionString; /// /// /// public async Task ExecuteCommandAsync(EvaluatedQuery evaluatedQuery) { using var connection = CreateConnection(); connection.Open(); var command = CreateCommand(evaluatedQuery.Query, connection); AddCommandParameters(command, evaluatedQuery.Parameters); var result = await command.ExecuteNonQueryAsync(); return result; } /// /// /// public async Task ExecuteScalarAsync(EvaluatedQuery evaluatedQuery) { using var connection = CreateConnection(); connection.Open(); var command = CreateCommand(evaluatedQuery.Query, connection); AddCommandParameters(command, evaluatedQuery.Parameters); var result = await command.ExecuteScalarAsync(); return result; } /// /// /// public async Task ExecuteQueryAsync(EvaluatedQuery evaluatedQuery) { using var connection = CreateConnection(); connection.Open(); var command = CreateCommand(evaluatedQuery.Query, connection); AddCommandParameters(command, evaluatedQuery.Parameters); using var reader = await command.ExecuteReaderAsync(); return await Task.FromResult(ReadAsDataSet(reader)); } /// /// Add parameters into the query to prevent SQL injection. /// /// Command to add the parameters to /// Parameters to add /// private DbCommand AddCommandParameters(DbCommand command, Dictionary parameters) { // Add parameters dynamically foreach (var param in parameters) { var dbParam = command.CreateParameter(); dbParam.ParameterName = param.Key; dbParam.Value = param.Value ?? DBNull.Value; command.Parameters.Add(dbParam); } return command; } /// /// Returns data as a . /// /// Reader to return data from. /// of data. private DataSet ReadAsDataSet(IDataReader reader) { var dataSet = new DataSet("dataset"); dataSet.Tables.Add(ReadAsDataTable(reader)); return dataSet; } /// /// Returns data as a . /// /// Reader to return data from. /// of data. private DataTable ReadAsDataTable(IDataReader reader) { var data = new DataTable(); var schemaTable =reader.GetSchemaTable(); foreach (DataRow row in schemaTable.Rows) { string colName = row.Field("ColumnName"); Type t = row.Field("DataType"); data.Columns.Add(colName, t); } while (reader.Read()) { var newRow = data.Rows.Add(); foreach (DataColumn col in data.Columns) { newRow[col.ColumnName] = reader[col.ColumnName]; } } return data; } }