Wrap SQL execution in try-catch and inject SqlExceptionOptions. Throw BadRequestException with a clear message when insert fails due to missing referenced entities, based on SqlException number. Other SQL exceptions are rethrown. This provides better feedback for foreign key/reference errors.
151 lines
9.3 KiB
C#
151 lines
9.3 KiB
C#
using DigitalData.Core.Abstraction.Application.Repository;
|
|
using DigitalData.Core.Exceptions;
|
|
using MediatR;
|
|
using Microsoft.Data.SqlClient;
|
|
using ReC.Application.Common.Exceptions;
|
|
using ReC.Application.EndpointAuth.Commands;
|
|
using ReC.Application.EndpointParams.Commands;
|
|
using ReC.Application.Endpoints.Commands;
|
|
using ReC.Application.Results.Commands;
|
|
using ReC.Application.Profile.Commands;
|
|
using ReC.Application.Common.Options;
|
|
|
|
namespace ReC.Application.Common.Procedures.InsertProcedure;
|
|
|
|
public record InsertObjectProcedure : IRequest<long>
|
|
{
|
|
/// <summary>
|
|
/// Target entity: ACTION, ENDPOINT, ENDPOINT_AUTH, ENDPOINT_PARAMS, PROFILE, RESULT
|
|
/// </summary>
|
|
public string Entity { get; set; } = null!;
|
|
|
|
internal string? AddedWho { get; private set; }
|
|
|
|
public InsertObjectProcedure AddedBy(string? addedWho = null)
|
|
{
|
|
AddedWho = addedWho ?? "ReC.API";
|
|
return this;
|
|
}
|
|
|
|
public InsertActionProcedure Action { get; set; } = new();
|
|
public InsertEndpointProcedure Endpoint { get; set; } = new();
|
|
public InsertEndpointAuthProcedure EndpointAuth { get; set; } = new();
|
|
public InsertProfileProcedure Profile { get; set; } = new();
|
|
public InsertResultProcedure Result { get; set; } = new();
|
|
public InsertEndpointParamsProcedure EndpointParams { get; set; } = new();
|
|
}
|
|
|
|
public static class InsertObjectProcedureExtensions
|
|
{
|
|
public static Task<long> ExecuteInsertProcedure(this ISender sender, IInsertProcedure procedure, string? addedWho = null, CancellationToken cancel = default)
|
|
{
|
|
return sender.Send(procedure.ToObjectProcedure(addedWho ?? "Rec.API"), cancel);
|
|
}
|
|
}
|
|
|
|
public class InsertObjectProcedureHandler(IRepository repo, SqlExceptionOptions sqlExceptionOptions) : IRequestHandler<InsertObjectProcedure, long>
|
|
{
|
|
public async Task<long> Handle(InsertObjectProcedure request, CancellationToken cancel)
|
|
{
|
|
var parameters = new[]
|
|
{
|
|
new SqlParameter("@pENTITY", request.Entity ?? (object)DBNull.Value),
|
|
|
|
new SqlParameter("@pADDED_WHO", (object?)request.AddedWho ?? DBNull.Value),
|
|
new SqlParameter("@pADDED_WHEN", (object?)DateTime.UtcNow ?? DBNull.Value),
|
|
|
|
new SqlParameter("@pACTION_PROFILE_ID", (object?)request.Action.ProfileId ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_ACTIVE", (object?)request.Action.Active ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_SEQUENCE", (object?)request.Action.Sequence ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_ENDPOINT_ID", (object?)request.Action.EndpointId ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_ENDPOINT_AUTH_ID", (object?)request.Action.EndpointAuthId ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_ENDPOINT_PARAMS_ID", (object?)request.Action.EndpointParamsId ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_SQL_CONNECTION_ID", (object?)request.Action.SqlConnectionId ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_TYPE_ID", (object?)request.Action.TypeId ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_PRE_SQL", (object?)request.Action.PreSql ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_HEADER_SQL", (object?)request.Action.HeaderSql ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_BODY_SQL", (object?)request.Action.BodySql ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_POST_SQL", (object?)request.Action.PostSql ?? DBNull.Value),
|
|
new SqlParameter("@pACTION_ERROR_ACTION_ID", (object?)request.Action.ErrorActionId ?? DBNull.Value),
|
|
|
|
new SqlParameter("@pENDPOINT_ACTIVE", (object?)request.Endpoint.Active ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_DESCRIPTION", (object?)request.Endpoint.Description ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_URI", (object?)request.Endpoint.Uri ?? DBNull.Value),
|
|
|
|
new SqlParameter("@pENDPOINT_AUTH_ACTIVE", (object?)request.EndpointAuth.Active ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_DESCRIPTION", (object?)request.EndpointAuth.Description ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_TYPE_ID", (object?)request.EndpointAuth.TypeId ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_API_KEY", (object?)request.EndpointAuth.ApiKey ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_API_VALUE", (object?)request.EndpointAuth.ApiValue ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_API_KEY_ADD_TO_ID", (object?)request.EndpointAuth.ApiKeyAddToId ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_TOKEN", (object?)request.EndpointAuth.Token ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_USERNAME", (object?)request.EndpointAuth.Username ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_PASSWORD", (object?)request.EndpointAuth.Password ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_DOMAIN", (object?)request.EndpointAuth.Domain ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_AUTH_WORKSTATION", (object?)request.EndpointAuth.Workstation ?? DBNull.Value),
|
|
|
|
new SqlParameter("@pPROFILE_ACTIVE", (object?)request.Profile.Active ?? DBNull.Value),
|
|
new SqlParameter("@pPROFILE_TYPE_ID", (object?)request.Profile.TypeId ?? DBNull.Value),
|
|
new SqlParameter("@pPROFILE_MANDANTOR", (object?)request.Profile.Mandantor ?? DBNull.Value),
|
|
new SqlParameter("@pPROFILE_NAME", (object?)request.Profile.Name ?? DBNull.Value),
|
|
new SqlParameter("@pPROFILE_DESCRIPTION", (object?)request.Profile.Description ?? DBNull.Value),
|
|
new SqlParameter("@pPROFILE_LOG_LEVEL_ID", (object?)request.Profile.LogLevelId ?? DBNull.Value),
|
|
new SqlParameter("@pPROFILE_LANGUAGE_ID", (object?)request.Profile.LanguageId ?? DBNull.Value),
|
|
|
|
new SqlParameter("@pRESULT_ACTION_ID", (object?)request.Result.ActionId ?? DBNull.Value),
|
|
new SqlParameter("@pRESULT_STATUS_ID", (object?)request.Result.StatusId ?? DBNull.Value),
|
|
new SqlParameter("@pRESULT_HEADER", (object?)request.Result.Header ?? DBNull.Value),
|
|
new SqlParameter("@pRESULT_BODY", (object?)request.Result.Body ?? DBNull.Value),
|
|
|
|
new SqlParameter("@pENDPOINT_PARAMS_ACTIVE", (object?)request.EndpointParams.Active ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_PARAMS_DESCRIPTION", (object?)request.EndpointParams.Description ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_PARAMS_GROUP_ID", (object?)request.EndpointParams.GroupId ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_PARAMS_SEQUENCE", (object?)request.EndpointParams.Sequence ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_PARAMS_KEY", (object?)request.EndpointParams.Key ?? DBNull.Value),
|
|
new SqlParameter("@pENDPOINT_PARAMS_VALUE", (object?)request.EndpointParams.Value ?? DBNull.Value),
|
|
|
|
new SqlParameter
|
|
{
|
|
ParameterName = "@oGUID",
|
|
SqlDbType = System.Data.SqlDbType.BigInt,
|
|
Direction = System.Data.ParameterDirection.Output
|
|
}
|
|
};
|
|
|
|
try
|
|
{
|
|
await repo.ExecuteQueryRawAsync(
|
|
"EXEC [dbo].[PRREC_INSERT_OBJECT] " +
|
|
"@pENTITY, @pADDED_WHO, @pADDED_WHEN, " +
|
|
"@pACTION_PROFILE_ID, @pACTION_ACTIVE, @pACTION_SEQUENCE, @pACTION_ENDPOINT_ID, @pACTION_ENDPOINT_AUTH_ID, @pACTION_ENDPOINT_PARAMS_ID, @pACTION_SQL_CONNECTION_ID, @pACTION_TYPE_ID, @pACTION_PRE_SQL, @pACTION_HEADER_SQL, @pACTION_BODY_SQL, @pACTION_POST_SQL, @pACTION_ERROR_ACTION_ID, " +
|
|
"@pENDPOINT_ACTIVE, @pENDPOINT_DESCRIPTION, @pENDPOINT_URI, " +
|
|
"@pENDPOINT_AUTH_ACTIVE, @pENDPOINT_AUTH_DESCRIPTION, @pENDPOINT_AUTH_TYPE_ID, @pENDPOINT_AUTH_API_KEY, @pENDPOINT_AUTH_API_VALUE, @pENDPOINT_AUTH_API_KEY_ADD_TO_ID, @pENDPOINT_AUTH_TOKEN, @pENDPOINT_AUTH_USERNAME, @pENDPOINT_AUTH_PASSWORD, @pENDPOINT_AUTH_DOMAIN, @pENDPOINT_AUTH_WORKSTATION, " +
|
|
"@pPROFILE_ACTIVE, @pPROFILE_TYPE_ID, @pPROFILE_MANDANTOR, @pPROFILE_NAME, @pPROFILE_DESCRIPTION, @pPROFILE_LOG_LEVEL_ID, @pPROFILE_LANGUAGE_ID, " +
|
|
"@pRESULT_ACTION_ID, @pRESULT_STATUS_ID, @pRESULT_HEADER, @pRESULT_BODY, " +
|
|
"@pENDPOINT_PARAMS_ACTIVE, @pENDPOINT_PARAMS_DESCRIPTION, @pENDPOINT_PARAMS_GROUP_ID, @pENDPOINT_PARAMS_SEQUENCE, @pENDPOINT_PARAMS_KEY, @pENDPOINT_PARAMS_VALUE, " +
|
|
"@oGUID OUTPUT",
|
|
parameters,
|
|
cancel);
|
|
}
|
|
catch (SqlException ex)
|
|
{
|
|
if (sqlExceptionOptions.SqlExceptionNumber.Contains(ex.Number))
|
|
throw new BadRequestException(
|
|
$"Insert '{request.Entity}' failed because one or more referenced entities do not exist. " +
|
|
"Please verify the supplied identifiers and try again.\n" +
|
|
ex.Message, ex);
|
|
else
|
|
throw;
|
|
}
|
|
|
|
var guidParam = parameters.Last();
|
|
|
|
if (guidParam.Value != DBNull.Value)
|
|
if (guidParam.Value is long longValue)
|
|
return longValue;
|
|
else if (long.TryParse(guidParam.Value.ToString(), out var guid))
|
|
return guid;
|
|
|
|
throw new InsertObjectFailedException(request, "InsertObject stored procedure did not return a valid identifier.");
|
|
}
|
|
} |