using DigitalData.Core.Abstraction.Application.Repository; using DigitalData.Core.Exceptions; using MediatR; 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; public record DeleteObjectProcedure : IRequest { /// /// Target entity: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT /// public string Entity { get; set; } = null!; /// /// Start GUID/ID (inclusive) /// public long Start { get; set; } /// /// End GUID/ID (inclusive). If 0, will be set to Start value. /// public long End { get; set; } /// /// If true, delete even if dependent data exists /// public bool Force { get; set; } } public class DeleteObjectProcedureHandler(IRepository repo, IOptionsMonitor sqlExOpt) : IRequestHandler { public async Task Handle(DeleteObjectProcedure request, CancellationToken cancel) { var execSql = new StringBuilder("EXEC @RC = [dbo].[PRREC_DELETE_OBJECT]"); var parameters = new List(); var separator = ' '; void Add(string name, object? value) { if (value is null) return; execSql.AppendLine($"{separator}@{name} = @{name}"); separator = ','; parameters.Add(new SqlParameter($"@{name}", value)); } 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(execSql).AppendLine(";") .AppendLine("SELECT @RC;") .ToString(); try { var result = await repo.ExecuteQueryRawAsync(sql, parameters.ToArray(), cancel); if (result > 0) { throw new DeleteObjectFailedException(request, $"DeleteObject stored procedure failed with error code: {result}"); } return result; } catch (SqlException ex) { if (sqlExOpt.CurrentValue.BadRequestSqlExceptionNumbers.Contains(ex.Number)) throw new BadRequestException(ex.Message, ex); else throw; } } }