using System.Data; using System.Diagnostics; using Microsoft.Data.SqlClient; namespace Management.Data; public class SqlService { private readonly IConfiguration _config; private readonly ILogger _logger; public SqlService(IConfiguration config, ILogger logger) { _config = config; _logger = logger; } private string GetConnectionString() { var cs = _config.GetConnectionString("Sql"); if (string.IsNullOrWhiteSpace(cs)) throw new InvalidOperationException("Missing ConnectionStrings:Sql"); return cs; } /// /// Execute stored procedure with standard signature: /// @action varchar, @rqst nvarchar(max), @resp nvarchar(max) OUTPUT /// public async Task ExecProcAsync( string procName, string action, string rqstJson, int commandTimeoutSeconds = 60, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(procName)) throw new ArgumentException("procName is required.", nameof(procName)); if (string.IsNullOrWhiteSpace(action)) throw new ArgumentException("action is required.", nameof(action)); if (string.IsNullOrWhiteSpace(rqstJson)) rqstJson = "{}"; var sw = Stopwatch.StartNew(); try { await using var conn = new SqlConnection(GetConnectionString()); await conn.OpenAsync(ct); await using var cmd = new SqlCommand(procName, conn) { CommandType = CommandType.StoredProcedure, CommandTimeout = commandTimeoutSeconds }; cmd.Parameters.Add(new SqlParameter("@action", SqlDbType.VarChar, 50) { Value = action }); cmd.Parameters.Add(new SqlParameter("@rqst", SqlDbType.NVarChar, -1) { Value = rqstJson }); var pResp = new SqlParameter("@resp", SqlDbType.NVarChar, -1) { Direction = ParameterDirection.Output }; cmd.Parameters.Add(pResp); await cmd.ExecuteNonQueryAsync(ct); var resp = pResp.Value as string ?? ""; sw.Stop(); _logger.LogInformation("SQL ok: {Proc}.{Action} ms={Ms}", procName, action, sw.ElapsedMilliseconds); return resp; } catch (Exception ex) { sw.Stop(); _logger.LogError(ex, "SQL error: {Proc}.{Action} ms={Ms}", procName, action, sw.ElapsedMilliseconds); throw; } } }