From 93b5f976d35af4a3a4604525d2b42bce49e33b7d Mon Sep 17 00:00:00 2001 From: TekH Date: Mon, 30 Mar 2026 09:30:07 +0200 Subject: [PATCH] Refactor stored procedure SQL construction and execution Centralize stored procedure SQL generation in StoredProcedureBuilder, allowing handlers to specify procedure name and return variable. Removes manual SQL string building from DeleteObjectProcedure and UpdateObjectProcedure handlers, reducing boilerplate and improving maintainability. --- .../DeleteProcedure/DeleteObjectProcedure.cs | 11 ++------ .../Procedures/StoredProcedureBuilder.cs | 27 ++++++++++++------- .../UpdateProcedure/UpdateObjectProcedure.cs | 11 ++------ 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/src/ReC.Application/Common/Procedures/DeleteProcedure/DeleteObjectProcedure.cs b/src/ReC.Application/Common/Procedures/DeleteProcedure/DeleteObjectProcedure.cs index cddc69f..3083a51 100644 --- a/src/ReC.Application/Common/Procedures/DeleteProcedure/DeleteObjectProcedure.cs +++ b/src/ReC.Application/Common/Procedures/DeleteProcedure/DeleteObjectProcedure.cs @@ -5,7 +5,6 @@ using Microsoft.Data.SqlClient; using Microsoft.Extensions.Options; using ReC.Application.Common.Exceptions; using ReC.Application.Common.Options; -using System.Text; namespace ReC.Application.Common.Procedures.DeleteProcedure; @@ -36,21 +35,15 @@ public class DeleteObjectProcedureHandler(IRepository repo, IOptionsMonitor Handle(DeleteObjectProcedure request, CancellationToken cancel) { - var sp = new StoredProcedureBuilder("EXEC @RC = [dbo].[PRREC_DELETE_OBJECT]") + var sp = new StoredProcedureBuilder("[dbo].[PRREC_DELETE_OBJECT]", "RC") .Add("pENTITY", request.Entity) .Add("pSTART", request.Start.ToString()) .Add("pEND", request.End.ToString()) .Add("pFORCE", request.Force); - var sql = new StringBuilder() - .AppendLine("DECLARE @RC SMALLINT = 0;") - .Append(sp.BuildSql()).AppendLine(";") - .AppendLine("SELECT @RC;") - .ToString(); - try { - var result = await repo.ExecuteQueryRawAsync(sql, sp.BuildParameters(), cancel); + var result = await repo.ExecuteQueryRawAsync(sp.BuildSql(), sp.BuildParameters(), cancel); if (result > 0) { diff --git a/src/ReC.Application/Common/Procedures/StoredProcedureBuilder.cs b/src/ReC.Application/Common/Procedures/StoredProcedureBuilder.cs index 5cccae0..bc4cae9 100644 --- a/src/ReC.Application/Common/Procedures/StoredProcedureBuilder.cs +++ b/src/ReC.Application/Common/Procedures/StoredProcedureBuilder.cs @@ -4,22 +4,19 @@ using System.Text; namespace ReC.Application.Common.Procedures; -internal sealed class StoredProcedureBuilder +internal sealed class StoredProcedureBuilder(string procedureName, string? returnVariable = null) { - private readonly StringBuilder _sql; + private readonly StringBuilder _execSql = returnVariable is not null + ? new StringBuilder($"EXEC @{returnVariable} = {procedureName}") + : new StringBuilder($"EXEC {procedureName}"); private readonly List _parameters = []; private char _separator = ' '; - public StoredProcedureBuilder(string execPrefix) - { - _sql = new StringBuilder(execPrefix); - } - public StoredProcedureBuilder Add(string name, object? value, SqlDbType? dbType = null) { if (value is null) return this; - _sql.AppendLine($"{_separator}@{name} = @{name}"); + _execSql.AppendLine($"{_separator}@{name} = @{name}"); _separator = ','; if (dbType.HasValue) @@ -32,7 +29,7 @@ internal sealed class StoredProcedureBuilder public StoredProcedureBuilder AddOutput(string name, SqlDbType dbType) { - _sql.AppendLine($"{_separator}@{name} = @{name} OUTPUT"); + _execSql.AppendLine($"{_separator}@{name} = @{name} OUTPUT"); _separator = ','; _parameters.Add(new SqlParameter @@ -45,7 +42,17 @@ internal sealed class StoredProcedureBuilder return this; } - public string BuildSql() => _sql.ToString(); + public string BuildSql() + { + if (returnVariable is null) + return _execSql.ToString(); + + return new StringBuilder() + .AppendLine($"DECLARE @{returnVariable} SMALLINT = 0;") + .Append(_execSql).AppendLine(";") + .AppendLine($"SELECT @{returnVariable};") + .ToString(); + } public SqlParameter[] BuildParameters() => [.. _parameters]; diff --git a/src/ReC.Application/Common/Procedures/UpdateProcedure/UpdateObjectProcedure.cs b/src/ReC.Application/Common/Procedures/UpdateProcedure/UpdateObjectProcedure.cs index dffec2d..9062237 100644 --- a/src/ReC.Application/Common/Procedures/UpdateProcedure/UpdateObjectProcedure.cs +++ b/src/ReC.Application/Common/Procedures/UpdateProcedure/UpdateObjectProcedure.cs @@ -7,7 +7,6 @@ using ReC.Application.Common.Exceptions; using ReC.Application.Common.Options; using ReC.Application.Common.Procedures.UpdateProcedure.Dto; using System.Data; -using System.Text; namespace ReC.Application.Common.Procedures.UpdateProcedure; @@ -38,7 +37,7 @@ public class UpdateObjectProcedureHandler(IRepository repo, IOptionsMonitor Handle(UpdateObjectProcedure request, CancellationToken cancel) { - var sp = new StoredProcedureBuilder("EXEC @RC = [dbo].[PRREC_UPDATE_OBJECT]") + var sp = new StoredProcedureBuilder("[dbo].[PRREC_UPDATE_OBJECT]", "RC") .Add("pENTITY", request.Entity) .Add("pGUID", request.Id) .Add("pCHANGED_WHO", request.ChangedWho) @@ -91,15 +90,9 @@ public class UpdateObjectProcedureHandler(IRepository repo, IOptionsMonitor 0) {