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 parameters = new[] { new SqlParameter("@pENTITY", request.Entity ?? (object)DBNull.Value), new SqlParameter("@pSTART", request.Start.ToString()), new SqlParameter("@pEND", request.End.ToString()), new SqlParameter("@pFORCE", (object?)request.Force ?? DBNull.Value) }; try { var sql = new StringBuilder() .AppendLine("DECLARE @RC SMALLINT = 0;") .AppendLine("EXEC @RC = [dbo].[PRREC_DELETE_OBJECT]") .AppendLine(" @pENTITY = @pENTITY,") .AppendLine(" @pSTART = @pSTART,") .AppendLine(" @pEND = @pEND,") .AppendLine(" @pFORCE = @pFORCE;") .AppendLine("SELECT @RC;") .ToString(); var result = await repo.ExecuteQueryRawAsync(sql, parameters, cancel); // The stored procedure returns 0 on success, error codes > 0 on failure 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; } } }