33 Commits

Author SHA1 Message Date
e96773f3c4 Remove DbModelConfigurationException and related logic
Removed the DbModelConfigurationException class and all its usages from DbModelOptions and EntityOptions. Indexers in these classes no longer throw this exception when configuration is missing. Updated the project file to include the Common\Options\DbModel\ folder.
2026-03-26 10:34:24 +01:00
06e92b588f Remove DbModel configuration and related JSON file
Removed all references to DbModel configuration from Program.cs and RecApplicationTestBase.cs. Deleted appsettings.DbModel.json, eliminating custom entity and column mapping definitions. The application no longer loads or uses DbModel configuration from JSON.
2026-03-26 10:34:05 +01:00
b922cbbb30 Remove ConfigureDbModel from dependency injection setup
Eliminated all references to ConfigureDbModel in DependencyInjection.cs, including related imports, configuration methods, and required service tracking. Dependency injection configuration is otherwise unchanged.
2026-03-26 10:32:24 +01:00
6c56375e3e Refactor RecDbContext to remove dynamic view mapping
Removed dependency on DbModelOptions and IOptions. Entity-to-view mappings are now hardcoded in OnModelCreating with fixed view names and schema. Property-to-column mappings now use EF Core conventions. Simplifies configuration and maintenance, but reduces flexibility for schema changes. Entity relationships remain explicitly configured.
2026-03-26 10:31:48 +01:00
fa9aa23f32 Add EF Core data annotations to view models
Added [Key], [Column], and [Table] attributes to ProfileView, RecActionView, and ResultView classes to explicitly map properties to database columns and views. Expanded model properties for clearer schema alignment and improved maintainability with Entity Framework Core.
2026-03-26 10:30:00 +01:00
b86d0c0f99 Add [Column] mapping attributes to query result classes
Added [Column] attributes to properties in BodyQueryResult, HeaderQueryResult, and InsertObjectResult to explicitly map them to their respective database columns. Also included necessary using directives for DataAnnotations.Schema to support these mappings. This enhances ORM compatibility and ensures correct property-to-column mapping.
2026-03-26 10:28:52 +01:00
b0d89ceba4 Remove properties from RecActionOptions class
Removed AddedWho and UseHttp1ForNtlm properties from RecActionOptions, leaving the class empty. This change cleans up unused configuration options.
2026-03-25 16:13:32 +01:00
11ebfdd21e Refactor DbModelOptions to use indexers for lookups
Replaced GetEntity and GetColumn extension methods with indexers
on DbModelOptions and EntityOptions. Updated all usages to use
the new indexer syntax, improving code clarity and error handling
for missing entity or column configurations.
2026-03-25 16:10:50 +01:00
1467acc4a1 Refactor DbModel options to use generic entity mapping
Replaces strongly-typed view options classes with a generic EntityOptions class and a dictionary-based configuration for entity-to-view and property-to-column mappings. Updates appsettings.DbModel.json to match the new structure. Refactors RecDbContext to use extension methods for mapping configuration. Removes obsolete options classes and simplifies exception handling for missing mappings. This change improves flexibility and maintainability of database view configuration.
2026-03-25 15:25:29 +01:00
e761fbd1ca Add DbModel config to Rec services setup
Added options.ConfigureDbModel to the AddRecServices configuration, enabling Rec services to use settings from the "DbModel" section of the app configuration for enhanced database model customization.
2026-03-25 13:30:12 +01:00
2e83d4a24a Make RecDbContext model mapping fully configurable
Refactored RecDbContext to use DbModelOptions injected via IOptions, replacing hardcoded view and column names with configuration-driven mappings. This enables dynamic control of entity-to-database mapping through appsettings.json, improving flexibility and maintainability.
2026-03-25 13:29:29 +01:00
37ba85d681 Add support for configuring DbModelOptions via DI
Introduce ConfigureDbModel methods to DependencyInjection for setting up DbModelOptions from code or configuration. Update required services tracking and add usage in Program.cs to enable structured DbModelOptions injection.
2026-03-25 13:26:54 +01:00
a46cd08122 Refactor DbModel options to use explicit, typed classes
Replaced the old generic, dictionary-based entity configuration system with a new, strongly-typed options structure under ReC.Application.Common.Options.DbModel. Introduced specific options classes for each major database view and result type, each with clear property mappings and defaults. Added a ViewOptions class for view/schema info. Removed all legacy entity mapping infrastructure, resulting in a more maintainable and type-safe configuration approach.
2026-03-25 12:53:10 +01:00
3d46901af5 Add DbModel view mappings to appsettings.DbModel.json
Added a new "DbModel" section to appsettings.DbModel.json, defining property-to-column mappings for RecActionView, ProfileView, ResultView, HeaderQueryResult, BodyQueryResult, and InsertObjectResult. This centralizes and standardizes database view and query result configurations.
2026-03-25 12:44:12 +01:00
90e8adbd36 Update behavior namespaces to InvokeAction for clarity
Renamed namespaces in PreprocessingBehavior and PostprocessingBehavior from .Action to .InvokeAction, and updated related using directives in DependencyInjection.cs. Added a folder entry for Common\Behaviors\Action\ in the project file for organization.
2026-03-25 11:43:30 +01:00
aef59def7f Add ResultType to InsertResultCommand in all handlers
Added the Type property (ResultType) to every InsertResultCommand sent in PostprocessingBehavior, PreprocessingBehavior, and InvokeRecActionViewCommand. This ensures each result now includes its context (Post, Pre, or Main), both in normal and exception flows.
2026-03-25 11:17:38 +01:00
d7783b6e81 Make InsertObjectProcedure properties nullable, require ResultType
Updated InsertObjectProcedure to make related command properties nullable and removed default initializations. Updated handler to use null-conditional access for these properties. Changed InsertResultCommand.Type to required and updated tests accordingly. Improves null safety and clarifies required fields.
2026-03-25 11:17:21 +01:00
4126f984e4 Expand and refactor OutResDto for richer data support
Refactored OutResDto to include additional properties such as Action, Profile, Status, and Type, and made several fields nullable. This enhances flexibility and allows for more comprehensive and optional data representation in API responses.
2026-03-25 11:06:07 +01:00
0e2328c287 Add support for Result.Info, Error, and Type in insert proc
Extended InsertObjectProcedureHandler to include Result.Info, Result.Error, and Result.Type in both the SQL parameter list and the command string. This ensures these fields are correctly passed to and handled by the stored procedure.
2026-03-25 11:02:56 +01:00
e04e054151 Add optional ResultType to InsertResultCommand
Added a nullable Type property of ResultType to InsertResultCommand for enhanced result categorization. Also included the required using directive for ReC.Domain.Constants.
2026-03-25 11:02:35 +01:00
6082a637fe Add mapping for result type fields in RecDbContext
Added entity property mappings for RESULT_TYPE_ID (Type) and RESULT_TYPE (TypeName) columns in RecDbContext to support storing and retrieving result type information.
2026-03-25 11:00:12 +01:00
93669a6358 Add Type and TypeName to ResultView model
Imported ResultType and added Type (ResultType?) and TypeName (string?) properties to ResultView to support representing result types alongside status information.
2026-03-25 10:59:33 +01:00
fecd9219b4 Add ResultType enum to ReC.Domain.Constants
Introduced a new ResultType enum with values Pre, Main, and Post to represent different result stages. Pre is explicitly set to 1.
2026-03-25 10:58:45 +01:00
bd07b4482c Remove CS0618 warning suppression for ExceptionHandlingMiddleware
Removed #pragma directives that suppressed CS0618 (obsolete API usage) warnings around app.UseMiddleware<ExceptionHandlingMiddleware>(). Obsolete warnings for this middleware will now be shown during compilation.
2026-03-25 10:28:49 +01:00
520aec427b Remove obsolete attribute and add exception using directive
Removed [Obsolete] from ExceptionHandlingMiddleware, indicating it is no longer deprecated. Added using directive for ReC.Application.Common.Exceptions to support updated exception handling.
2026-03-25 10:27:41 +01:00
26b7a82451 Handle RecActionException in middleware with 422 response
Added specific handling for RecActionException in the exception middleware. Now logs a warning with ActionId and ProfileId, returns a 422 Unprocessable Entity status, and provides detailed error information in the response.
2026-03-25 10:26:24 +01:00
08c0d29d84 Improve error handling and logging in batch rec actions
Add ILogger support to InvokeRecActionViewsCommandHandler for enhanced error and warning logging. Log and continue on handled exceptions when appropriate, and rethrow for critical errors. Clean up and reorder using directives. This increases robustness and traceability during batch rec action processing.
2026-03-25 10:25:52 +01:00
405b5f3ab1 Add ActionId and ProfileId properties to RecActionException
Expose ActionId and ProfileId as public properties in the
RecActionException class, allowing external access to these
values from exception instances. Refactored the constructor
to use a block body.
2026-03-25 10:17:24 +01:00
32af65d30c Remove InvokeBatchRecActionViewsCommand extension method
Deleted the InvokeBatchRecActionViewsCommandExtensions class and its InvokeBatchRecActionView extension method for ISender. The command record and handler remain unchanged.
2026-03-25 10:07:15 +01:00
30ccf05c57 Use RecActionException for contextual error handling
Replaced generic exception with RecActionException in PostprocessingBehavior when ErrorAction is Stop, providing ActionId and ProfileId for better error context. Added necessary using statements for the new exception and related namespaces.
2026-03-25 09:58:02 +01:00
a14d5ff112 Improve error handling with RecActionException
Wrap exceptions in PreprocessingBehavior with RecActionException, including ActionId and ProfileId for better context and debugging. This enhances error reporting when ErrorAction is set to Stop.
2026-03-25 09:57:46 +01:00
fec125b0d5 Improve exception context in action error handling
Updated InvokeRecActionViewCommandHandler to throw a RecActionException with action Id and ProfileId when an error occurs and ErrorAction is set to Stop. This change enhances error traceability by providing more contextual information in exceptions.
2026-03-25 09:56:58 +01:00
82ae4c5957 Add RecActionException custom exception class
Introduced RecActionException in ReC.Application.Common.Exceptions to encapsulate errors related to rec actions, including actionId, optional profileId, and inner exception details in the error message.
2026-03-25 09:55:52 +01:00
28 changed files with 245 additions and 244 deletions

View File

@@ -7,13 +7,11 @@ using System.Text.Json;
namespace ReC.API.Middleware;
//TODO: Fix and use DigitalData.Core.Exceptions.Middleware
/// <summary>
/// Middleware for handling exceptions globally in the application.
/// Captures exceptions thrown during the request pipeline execution,
/// logs them, and returns an appropriate HTTP response with a JSON error details.
/// </summary>
[Obsolete("Use DigitalData.Core.Exceptions.Middleware")]
public class ExceptionHandlingMiddleware
{
private readonly RequestDelegate _next;
@@ -164,6 +162,22 @@ public class ExceptionHandlingMiddleware
};
break;
case RecActionException recActionEx:
logger.LogWarning(
recActionEx,
"Rec action failed. ActionId: {ActionId}, ProfileId: {ProfileId}",
recActionEx.ActionId,
recActionEx.ProfileId);
context.Response.StatusCode = (int)HttpStatusCode.UnprocessableEntity;
details = new()
{
Title = "Rec Action Failed",
Detail = recActionEx.InnerException?.Message
?? "An error occurred while executing the rec action. Check the logs for more details."
};
break;
default:
logger.LogError(exception, "Unhandled exception occurred.");
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

View File

@@ -70,9 +70,7 @@ try
var app = builder.Build();
#pragma warning disable CS0618
app.UseMiddleware<ExceptionHandlingMiddleware>();
#pragma warning restore CS0618
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment() || config.GetValue<bool>("UseSwagger"))

View File

@@ -1,11 +1,12 @@
using MediatR;
using ReC.Application.Common.Exceptions;
using ReC.Application.Common.Interfaces;
using ReC.Application.RecActions.Commands;
using ReC.Application.Results.Commands;
using ReC.Domain.Constants;
using System.Text.Json;
namespace ReC.Application.Common.Behaviors.Action;
namespace ReC.Application.Common.Behaviors.InvokeAction;
public class PostprocessingBehavior(IRecDbContext context, ISender sender) : IPipelineBehavior<InvokeRecActionViewCommand, Unit>
{
@@ -23,7 +24,8 @@ public class PostprocessingBehavior(IRecDbContext context, ISender sender) : IPi
await sender.Send(new InsertResultCommand()
{
ActionId = request.Action.Id,
Info = info
Info = info,
Type = ResultType.Post
}, cancel);
}
}
@@ -34,11 +36,12 @@ public class PostprocessingBehavior(IRecDbContext context, ISender sender) : IPi
await sender.Send(new InsertResultCommand()
{
ActionId = request.Action.Id,
Error = error
Error = error,
Type = ResultType.Post
}, cancel);
if (request.Action.ErrorAction == ErrorAction.Stop)
throw;
throw new RecActionException(request.Action.Id, request.Action.ProfileId, ex);
}
return Unit.Value;

View File

@@ -1,11 +1,12 @@
using MediatR;
using ReC.Application.Common.Exceptions;
using ReC.Application.Common.Interfaces;
using ReC.Application.RecActions.Commands;
using ReC.Application.Results.Commands;
using ReC.Domain.Constants;
using System.Text.Json;
namespace ReC.Application.Common.Behaviors.Action;
namespace ReC.Application.Common.Behaviors.InvokeAction;
public class PreprocessingBehavior(IRecDbContext context, ISender sender) : IPipelineBehavior<InvokeRecActionViewCommand, Unit>
{
@@ -20,7 +21,8 @@ public class PreprocessingBehavior(IRecDbContext context, ISender sender) : IPip
await sender.Send(new InsertResultCommand()
{
ActionId = request.Action.Id,
Info = JsonSerializer.Serialize(result)
Info = JsonSerializer.Serialize(result),
Type = ResultType.Pre
}, cancel);
}
}
@@ -29,11 +31,12 @@ public class PreprocessingBehavior(IRecDbContext context, ISender sender) : IPip
await sender.Send(new InsertResultCommand()
{
ActionId = request.Action.Id,
Error = ex.ToString()
Error = ex.ToString(),
Type = ResultType.Pre
}, cancel);
if (request.Action.ErrorAction == ErrorAction.Stop)
throw;
throw new RecActionException(request.Action.Id, request.Action.ProfileId, ex);
}
return await next(cancel);

View File

@@ -1,10 +1,26 @@
namespace ReC.Application.Common.Dto;
using ReC.Domain.Constants;
namespace ReC.Application.Common.Dto;
public record OutResDto
{
public long Id { get; set; }
public long ActionId { get; set; }
public long? ActionId { get; set; }
public RecActionDto? Action { get; set; }
public long? ProfileId { get; set; }
public ProfileDto? Profile { get; set; }
public string? ProfileName { get; set; }
public short? StatusCode { get; set; }
public string? StatusName { get; set; }
public ResultType? Type { get; set; }
public string? Header { get; set; }
@@ -14,9 +30,9 @@ public record OutResDto
public string? Error { get; set; }
public string AddedWho { get; set; } = null!;
public string? AddedWho { get; set; }
public DateTime AddedWhen { get; set; }
public DateTime? AddedWhen { get; set; }
public string? ChangedWho { get; set; }

View File

@@ -0,0 +1,9 @@
namespace ReC.Application.Common.Exceptions;
public class RecActionException(long actionId, long? profileId, Exception innerException)
: Exception($"Rec action failed. ActionId: {actionId}, ProfileId: {profileId}", innerException)
{
public long ActionId { get; } = actionId;
public long? ProfileId { get; } = profileId;
}

View File

@@ -2,7 +2,5 @@
public class RecActionOptions
{
public string AddedWho { get; set; } = null!;
public bool UseHttp1ForNtlm { get; set; } = false;
}

View File

@@ -24,12 +24,12 @@ public record InsertObjectProcedure : IRequest<long>
//TODO: update to set in authentication middleware or similar, and remove from procedure properties
internal string? AddedWho { get; private set; } = "ReC.API";
public InsertActionCommand Action { get; set; } = new();
public InsertEndpointCommand Endpoint { get; set; } = new();
public InsertEndpointAuthCommand EndpointAuth { get; set; } = new();
public InsertProfileCommand Profile { get; set; } = new();
public InsertResultCommand Result { get; set; } = new();
public InsertEndpointParamsCommand EndpointParams { get; set; } = new();
public InsertActionCommand? Action { get; set; }
public InsertEndpointCommand? Endpoint { get; set; }
public InsertEndpointAuthCommand? EndpointAuth { get; set; }
public InsertProfileCommand? Profile { get; set; }
public InsertResultCommand? Result { get; set; }
public InsertEndpointParamsCommand? EndpointParams { get; set; }
}
public class InsertObjectProcedureHandler(IRepository repo, IOptionsMonitor<SqlExceptionOptions> sqlExOpt) : IRequestHandler<InsertObjectProcedure, long>
@@ -43,57 +43,58 @@ public class InsertObjectProcedureHandler(IRepository repo, IOptionsMonitor<SqlE
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?)(byte?)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("@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?)(byte?)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_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("@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("@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("@pRESULT_INFO", (object?)request.Result.Info ?? DBNull.Value),
new SqlParameter("@pRESULT_ERROR", (object?)request.Result.Error ?? 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("@pRESULT_INFO", (object?)request.Result?.Info ?? DBNull.Value),
new SqlParameter("@pRESULT_ERROR", (object?)request.Result?.Error ?? DBNull.Value),
new SqlParameter("@pRESULT_TYPE_ID", (object?)(byte?)request.Result?.Type ?? 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("@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
{
@@ -112,7 +113,7 @@ public class InsertObjectProcedureHandler(IRepository repo, IOptionsMonitor<SqlE
"@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, " +
"@pRESULT_ACTION_ID, @pRESULT_STATUS_ID, @pRESULT_HEADER, @pRESULT_BODY, @pRESULT_INFO, @pRESULT_ERROR, @pRESULT_TYPE_ID, " +
"@pENDPOINT_PARAMS_ACTIVE, @pENDPOINT_PARAMS_DESCRIPTION, @pENDPOINT_PARAMS_GROUP_ID, @pENDPOINT_PARAMS_SEQUENCE, @pENDPOINT_PARAMS_KEY, @pENDPOINT_PARAMS_VALUE, " +
"@oGUID OUTPUT",
parameters,

View File

@@ -3,7 +3,7 @@ using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ReC.Application.Common.Behaviors;
using ReC.Application.Common.Behaviors.Action;
using ReC.Application.Common.Behaviors.InvokeAction;
using ReC.Application.Common.Constants;
using ReC.Application.Common.Options;
using ReC.Application.RecActions.Commands;

View File

@@ -23,4 +23,9 @@
<ProjectReference Include="..\ReC.Domain\ReC.Domain.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Common\Behaviors\Action\" />
<Folder Include="Common\Options\DbModel\" />
</ItemGroup>
</Project>

View File

@@ -1,5 +1,6 @@
using DigitalData.Core.Abstractions.Interfaces;
using MediatR;
using MediatR;
using Microsoft.Extensions.Logging;
using ReC.Application.Common.Exceptions;
using ReC.Application.RecActions.Queries;
using ReC.Domain.Constants;
@@ -10,13 +11,7 @@ public record InvokeBatchRecActionViewsCommand : IRequest
public long ProfileId { get; init; }
}
public static class InvokeBatchRecActionViewsCommandExtensions
{
public static Task InvokeBatchRecActionView(this ISender sender, long profileId, CancellationToken cancel = default)
=> sender.Send(new InvokeBatchRecActionViewsCommand { ProfileId = profileId }, cancel);
}
public class InvokeRecActionViewsCommandHandler(ISender sender) : IRequestHandler<InvokeBatchRecActionViewsCommand>
public class InvokeRecActionViewsCommandHandler(ISender sender, ILogger<InvokeRecActionViewsCommandHandler>? logger = null) : IRequestHandler<InvokeBatchRecActionViewsCommand>
{
public async Task Handle(InvokeBatchRecActionViewsCommand request, CancellationToken cancel)
{
@@ -28,11 +23,24 @@ public class InvokeRecActionViewsCommandHandler(ISender sender) : IRequestHandle
{
await sender.Send(new InvokeRecActionViewCommand() { Action = action }, cancel);
}
catch
catch (RecActionException ex)
{
switch (action.ErrorAction)
{
case ErrorAction.Continue:
logger?.LogWarning(ex, "Rec action failed but continuing. ActionId: {ActionId}, ProfileId: {ProfileId}", ex.ActionId, ex.ProfileId);
break;
default:
// Rethrow the exception to stop processing further actions
throw;
}
}
catch (Exception ex)
{
switch (action.ErrorAction)
{
case ErrorAction.Continue:
logger?.LogError(ex, "Unexpected error during rec action. ActionId: {ActionId}, ProfileId: {ProfileId}", action.Id, action.ProfileId);
break;
default:
// Rethrow the exception to stop processing further actions

View File

@@ -149,7 +149,8 @@ public class InvokeRecActionViewCommandHandler(
StatusId = statusCode,
ActionId = action.Id,
Header = JsonSerializer.Serialize(resHeaders, options: new() { WriteIndented = false }),
Body = resBody
Body = resBody,
Type = ResultType.Main
}, cancel);
}
catch(Exception ex)
@@ -157,11 +158,12 @@ public class InvokeRecActionViewCommandHandler(
await sender.Send(new InsertResultCommand()
{
ActionId = action.Id,
Error = ex.ToString()
Error = ex.ToString(),
Type = ResultType.Main
}, cancel);
if (action.ErrorAction == ErrorAction.Stop)
throw;
throw new RecActionException(action.Id, action.ProfileId, ex);
}
finally
{

View File

@@ -1,5 +1,6 @@
using MediatR;
using ReC.Application.Common.Procedures.InsertProcedure;
using ReC.Domain.Constants;
namespace ReC.Application.Results.Commands;
@@ -11,6 +12,7 @@ public record InsertResultCommand : IInsertProcedure
public string? Body { get; set; }
public string? Info { get; set; }
public string? Error { get; set; }
public required ResultType Type { get; set; }
}
public class InsertResultProcedureHandler(ISender sender) : IRequestHandler<InsertResultCommand, long>

View File

@@ -0,0 +1,8 @@
namespace ReC.Domain.Constants;
public enum ResultType
{
Pre = 1,
Main,
Post
}

View File

@@ -1,6 +1,9 @@
namespace ReC.Domain.QueryOutput;
using System.ComponentModel.DataAnnotations.Schema;
namespace ReC.Domain.QueryOutput;
public class BodyQueryResult
{
[Column("REQUEST_BODY")]
public string? RawBody { get; init; }
}

View File

@@ -1,6 +1,9 @@
namespace ReC.Domain.QueryOutput;
using System.ComponentModel.DataAnnotations.Schema;
namespace ReC.Domain.QueryOutput;
public class HeaderQueryResult
{
[Column("REQUEST_HEADER")]
public string? RawHeader { get; init; }
}

View File

@@ -4,5 +4,6 @@ namespace ReC.Domain.QueryOutput;
public class InsertObjectResult
{
[Column("oGUID")]
public required long NewObjectId { get; set; }
}

View File

@@ -1,4 +1,5 @@
using ReC.Domain.Constants;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ReC.Domain.Views;
@@ -8,39 +9,58 @@ public record ProfileView
{
public virtual IEnumerable<RecActionView>? Actions { get; init; }
[Key]
[Column("PROFILE_GUID")]
public long Id { get; init; }
[Column("ACTIVE")]
public bool Active { get; init; }
[Column("TYPE_ID")]
public ProfileType TypeId { get; init; }
[Column("TYPE")]
public string? Type { get; init; }
[Column("MANDANTOR")]
public string? Mandantor { get; init; }
[Column("PROFILE_NAME")]
public string? ProfileName { get; init; }
[Column("DESCRIPTION")]
public string? Description { get; init; }
[Column("LOG_LEVEL_ID")]
public byte LogLevelId { get; init; }
[Column("LOG_LEVEL")]
public string? LogLevel { get; init; }
[Column("LANGUAGE_ID")]
public short LanguageId { get; init; }
[Column("LANGUAGE")]
public string? Language { get; init; }
[Column("ADDED_WHO")]
public string? AddedWho { get; init; }
[Column("ADDED_WHEN")]
public DateTime AddedWhen { get; init; }
[Column("CHANGED_WHO")]
public string? ChangedWho { get; init; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; init; }
[Column("FIRST_RUN")]
public DateTime? FirstRun { get; init; }
[Column("LAST_RUN")]
public DateTime? LastRun { get; init; }
[Column("LAST_RESULT")]
public string? LastResult { get; init; }
}

View File

@@ -1,4 +1,5 @@
using ReC.Domain.Constants;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ReC.Domain.Views;
@@ -16,72 +17,106 @@ public class RecActionView
{
public virtual IEnumerable<ResultView>? Results { get; set; }
[Key]
[Column("ACTION_GUID")]
public required long Id { get; set; }
[Column("PROFILE_ID")]
public long? ProfileId { get; set; }
[ForeignKey("ProfileId")]
public ProfileView? Profile { get; set; }
[Column("PROFILE_NAME")]
public string? ProfileName { get; set; }
[Column("PROFILE_TYPE_ID")]
public ProfileType? ProfileType { get; set; }
[Column("SEQUENCE")]
public byte? Sequence { get; set; }
[Column("ENDPOINT_ID")]
public long? EndpointId { get; set; }
[Column("ENDPOINT_URI")]
public string? EndpointUri { get; set; }
[Column("ENDPOINT_AUTH_ID")]
public long? EndpointAuthId { get; set; }
[Column("ENDPOINT_AUTH_TYPE_ID")]
public EndpointAuthType? EndpointAuthType { get; set; }
[Column("ENDPOINT_AUTH_TYPE")]
public string? EndpointAuthTypeName { get; set; }
[Column("ENDPOINT_AUTH_API_KEY")]
public string? EndpointAuthApiKey { get; set; }
[Column("ENDPOINT_AUTH_API_VALUE")]
public string? EndpointAuthApiValue { get; set; }
[Column("ENDPOINT_AUTH_API_KEY_ADD_TO_ID")]
public ApiKeyLocation? EndpointAuthApiKeyAddTo { get; set; }
[Column("ENDPOINT_AUTH_API_KEY_ADD_TO")]
public string? EndpointAuthApiKeyAddToName { get; set; }
[Column("ENDPOINT_AUTH_TOKEN")]
public string? EndpointAuthToken { get; set; }
[Column("ENDPOINT_AUTH_USERNAME")]
public string? EndpointAuthUsername { get; set; }
[Column("ENDPOINT_AUTH_PASSWORD")]
public string? EndpointAuthPassword { get; set; }
[Column("ENDPOINT_AUTH_DOMAIN")]
public string? EndpointAuthDomain { get; set; }
[Column("ENDPOINT_AUTH_WORKSTATION")]
public string? EndpointAuthWorkstation { get; set; }
[Column("ENDPOINT_PARAMS_ID")]
public short? EndpointParamsId { get; set; }
[Column("SQL_CONNECTION_ID")]
public short? SqlConnectionId { get; set; }
[Column("SQL_CONNECTION_SERVER")]
public string? SqlConnectionServer { get; set; }
[Column("SQL_CONNECTION_DB")]
public string? SqlConnectionDb { get; set; }
[Column("SQL_CONNECTION_USERNAME")]
public string? SqlConnectionUsername { get; set; }
[Column("SQL_CONNECTION_PASSWORD")]
public string? SqlConnectionPassword { get; set; }
[Column("REST_TYPE_ID")]
public RestType? RestType { get; set; }
[Column("REST_TYPE")]
public string? RestTypeName { get; set; }
[Column("PREPROCESSING_QUERY")]
public string? PreprocessingQuery { get; set; }
[Column("HEADER_QUERY")]
public string? HeaderQuery { get; set; }
[Column("BODY_QUERY")]
public string? BodyQuery { get; set; }
[Column("POSTPROCESSING_QUERY")]
public string? PostprocessingQuery { get; set; }
[Column("ERROR_ACTION_ID")]
public ErrorAction? ErrorAction { get; set; }
[Column("ERROR_ACTION")]
public string? ErrorActionName { get; set; }
}

View File

@@ -1,39 +1,62 @@
using System.ComponentModel.DataAnnotations.Schema;
using ReC.Domain.Constants;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace ReC.Domain.Views;
[Table("VWREC_RESULT", Schema = "dbo")]
public class ResultView
{
[Key]
[Column("RESULT_GUID")]
public long Id { get; set; }
[Column("ACTION_ID")]
public long? ActionId { get; set; }
public RecActionView? Action { get; set; }
[Column("PROFILE_ID")]
public long? ProfileId { get; set; }
public ProfileView? Profile { get; set; }
[Column("PROFILE_NAME")]
public string? ProfileName { get; set; }
[Column("STATUS_ID")]
public short? StatusCode { get; set; }
[Column("STATUS")]
public string? StatusName { get; set; }
[Column("RESULT_TYPE_ID")]
public ResultType? Type { get; set; }
[Column("RESULT_TYPE")]
public string? TypeName { get; set; }
[Column("RESULT_HEADER")]
public string? Header { get; set; }
[Column("RESULT_BODY")]
public string? Body { get; set; }
[Column("RESULT_INFO")]
public string? Info { get; set; }
[Column("RESULT_ERROR")]
public string? Error { get; set; }
[Column("ADDED_WHO")]
public string? AddedWho { get; set; }
[Column("ADDED_WHEN")]
public DateTime? AddedWhen { get; set; }
[Column("CHANGED_WHO")]
public string? ChangedWho { get; set; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; set; }
}

View File

@@ -1,12 +0,0 @@
namespace ReC.Infrastructure.Exceptions;
public class DbModelConfigurationException : Exception
{
public DbModelConfigurationException(string message) : base(message)
{
}
public DbModelConfigurationException()
{
}
}

View File

@@ -1,23 +0,0 @@
using ReC.Infrastructure.Exceptions;
using ReC.Infrastructure.Options.Shared;
namespace ReC.Infrastructure.Options;
public record DbModelOptions
{
public Dictionary<string, EntityOptions> Entities { get; init; } = [];
public Dictionary<string, VirtualEntityOptions> VirtualEntities { get; init; } = [];
public void EnsureEntity<T>(bool isVirtual)
{
var entities = isVirtual
? VirtualEntities.ToDictionary(kvp => kvp.Key, kvp => kvp.Value as EntityBaseOptions)
: Entities.ToDictionary(kvp => kvp.Key, kvp => kvp.Value as EntityBaseOptions);
if(entities.TryGetValue(nameof(T), out var entityOptions))
entityOptions.EnsureProperties<T>();
else
throw new DbModelConfigurationException($"Entity options for type '{typeof(T).FullName}' not found.");
}
}

View File

@@ -1,33 +0,0 @@
using ReC.Domain.Attributes;
using ReC.Infrastructure.Exceptions;
namespace ReC.Infrastructure.Options.Shared;
public record EntityBaseOptions()
{
public Dictionary<string, string> ColumnMappings { get; init; } = [];
public IEnumerable<string> PropertyNames => ColumnMappings.Select(col => col.Key);
public IEnumerable<string> ColumnNames => ColumnMappings.Select(col => col.Value);
public void EnsureProperties(IEnumerable<string> propertyNames)
{
var missingProperties = propertyNames.Except(PropertyNames).ToList();
if (missingProperties.Count != 0)
throw new DbModelConfigurationException($"The following properties are not configured: {string.Join(", ", missingProperties)}");
}
public void EnsureProperties(params string[] propertyNames)
=> EnsureProperties(propertyNames.AsEnumerable());
public void EnsureProperties<T>()
{
var propertyNames = typeof(T)
.GetProperties()
.Where(prop => Attribute.IsDefined(prop, typeof(MustConfiguredAttribute)))
.Select(prop => prop.Name);
EnsureProperties(propertyNames);
}
}

View File

@@ -1,3 +0,0 @@
namespace ReC.Infrastructure.Options.Shared;
public record EntityOptions(TableOptions Table) : EntityBaseOptions;

View File

@@ -1,3 +0,0 @@
namespace ReC.Infrastructure.Options.Shared;
public record TableOptions(string Name, string? Schema = null);

View File

@@ -1,3 +0,0 @@
namespace ReC.Infrastructure.Options.Shared;
public record VirtualEntityOptions : EntityBaseOptions;

View File

@@ -21,7 +21,6 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
public DbSet<InsertObjectResult> RecResults { get; set; }
#endregion DB Sets
// TODO: Update to configure via appsettings.json
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
@@ -29,41 +28,6 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
modelBuilder.Entity<RecActionView>(b =>
{
b.ToView("VWREC_ACTION", "dbo");
b.HasKey(e => e.Id);
b.Property(e => e.Id).HasColumnName("ACTION_GUID");
b.Property(e => e.ProfileId).HasColumnName("PROFILE_ID");
b.Property(e => e.ProfileName).HasColumnName("PROFILE_NAME");
b.Property(e => e.ProfileType).HasColumnName("PROFILE_TYPE_ID");
b.Property(e => e.Sequence).HasColumnName("SEQUENCE");
b.Property(e => e.EndpointId).HasColumnName("ENDPOINT_ID");
b.Property(e => e.EndpointUri).HasColumnName("ENDPOINT_URI");
b.Property(e => e.EndpointAuthId).HasColumnName("ENDPOINT_AUTH_ID");
b.Property(e => e.EndpointAuthType).HasColumnName("ENDPOINT_AUTH_TYPE_ID");
b.Property(e => e.EndpointAuthTypeName).HasColumnName("ENDPOINT_AUTH_TYPE");
b.Property(e => e.EndpointAuthApiKey).HasColumnName("ENDPOINT_AUTH_API_KEY");
b.Property(e => e.EndpointAuthApiValue).HasColumnName("ENDPOINT_AUTH_API_VALUE");
b.Property(e => e.EndpointAuthApiKeyAddTo).HasColumnName("ENDPOINT_AUTH_API_KEY_ADD_TO_ID");
b.Property(e => e.EndpointAuthApiKeyAddToName).HasColumnName("ENDPOINT_AUTH_API_KEY_ADD_TO");
b.Property(e => e.EndpointAuthToken).HasColumnName("ENDPOINT_AUTH_TOKEN");
b.Property(e => e.EndpointAuthUsername).HasColumnName("ENDPOINT_AUTH_USERNAME");
b.Property(e => e.EndpointAuthPassword).HasColumnName("ENDPOINT_AUTH_PASSWORD");
b.Property(e => e.EndpointAuthDomain).HasColumnName("ENDPOINT_AUTH_DOMAIN");
b.Property(e => e.EndpointAuthWorkstation).HasColumnName("ENDPOINT_AUTH_WORKSTATION");
b.Property(e => e.EndpointParamsId).HasColumnName("ENDPOINT_PARAMS_ID");
b.Property(e => e.SqlConnectionId).HasColumnName("SQL_CONNECTION_ID");
b.Property(e => e.SqlConnectionServer).HasColumnName("SQL_CONNECTION_SERVER");
b.Property(e => e.SqlConnectionDb).HasColumnName("SQL_CONNECTION_DB");
b.Property(e => e.SqlConnectionUsername).HasColumnName("SQL_CONNECTION_USERNAME");
b.Property(e => e.SqlConnectionPassword).HasColumnName("SQL_CONNECTION_PASSWORD");
b.Property(e => e.RestType).HasColumnName("REST_TYPE_ID");
b.Property(e => e.RestTypeName).HasColumnName("REST_TYPE");
b.Property(e => e.PreprocessingQuery).HasColumnName("PREPROCESSING_QUERY");
b.Property(e => e.HeaderQuery).HasColumnName("HEADER_QUERY");
b.Property(e => e.BodyQuery).HasColumnName("BODY_QUERY");
b.Property(e => e.PostprocessingQuery).HasColumnName("POSTPROCESSING_QUERY");
b.Property(e => e.ErrorAction).HasColumnName("ERROR_ACTION_ID");
b.Property(e => e.ErrorActionName).HasColumnName("ERROR_ACTION");
b.HasMany(e => e.Results)
.WithOne(r => r.Action)
@@ -73,46 +37,11 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
modelBuilder.Entity<ProfileView>(b =>
{
b.ToView("VWREC_PROFILE", "dbo");
b.HasKey(e => e.Id);
b.Property(e => e.Id).HasColumnName("PROFILE_GUID");
b.Property(e => e.Active).HasColumnName("ACTIVE");
b.Property(e => e.TypeId).HasColumnName("TYPE_ID");
b.Property(e => e.Type).HasColumnName("TYPE");
b.Property(e => e.Mandantor).HasColumnName("MANDANTOR");
b.Property(e => e.ProfileName).HasColumnName("PROFILE_NAME");
b.Property(e => e.Description).HasColumnName("DESCRIPTION");
b.Property(e => e.LogLevelId).HasColumnName("LOG_LEVEL_ID");
b.Property(e => e.LogLevel).HasColumnName("LOG_LEVEL");
b.Property(e => e.LanguageId).HasColumnName("LANGUAGE_ID");
b.Property(e => e.Language).HasColumnName("LANGUAGE");
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
b.Property(e => e.FirstRun).HasColumnName("FIRST_RUN");
b.Property(e => e.LastRun).HasColumnName("LAST_RUN");
b.Property(e => e.LastResult).HasColumnName("LAST_RESULT");
});
modelBuilder.Entity<ResultView>(b =>
{
b.ToView("VWREC_RESULT", "dbo");
b.HasKey(e => e.Id);
b.Property(e => e.Id).HasColumnName("RESULT_GUID");
b.Property(e => e.ActionId).HasColumnName("ACTION_ID");
b.Property(e => e.ProfileId).HasColumnName("PROFILE_ID");
b.Property(e => e.ProfileName).HasColumnName("PROFILE_NAME");
b.Property(e => e.StatusCode).HasColumnName("STATUS_ID");
b.Property(e => e.StatusName).HasColumnName("STATUS");
b.Property(e => e.Header).HasColumnName("RESULT_HEADER");
b.Property(e => e.Body).HasColumnName("RESULT_BODY");
b.Property(e => e.Info).HasColumnName("RESULT_INFO");
b.Property(e => e.Error).HasColumnName("RESULT_ERROR");
b.Property(e => e.AddedWho).HasColumnName("ADDED_WHO");
b.Property(e => e.AddedWhen).HasColumnName("ADDED_WHEN");
b.Property(e => e.ChangedWho).HasColumnName("CHANGED_WHO");
b.Property(e => e.ChangedWhen).HasColumnName("CHANGED_WHEN");
b.HasOne(r => r.Action)
.WithMany(a => a.Results)
@@ -126,19 +55,16 @@ public class RecDbContext(DbContextOptions<RecDbContext> options) : DbContext(op
modelBuilder.Entity<HeaderQueryResult>(b =>
{
b.HasNoKey();
b.Property(e => e.RawHeader).HasColumnName("REQUEST_HEADER");
});
modelBuilder.Entity<BodyQueryResult>(b =>
{
b.HasNoKey();
b.Property(e => e.RawBody).HasColumnName("REQUEST_BODY");
});
modelBuilder.Entity<InsertObjectResult>(b =>
{
b.HasNoKey();
b.Property(e => e.NewObjectId).HasColumnName("oGUID");
});
}
}

View File

@@ -23,7 +23,7 @@ public class ResultProcedureTests : RecApplicationTestBase
[Test]
public async Task InsertResultProcedure_runs_via_mediator()
{
var procedure = new InsertResultCommand { ActionId = 1, StatusId = 200, Header = "h", Body = "b" };
var procedure = new InsertResultCommand { ActionId = 1, StatusId = 200, Header = "h", Body = "b", Type = Domain.Constants.ResultType.Main };
var (sender, scope) = CreateScopedSender();
using var _ = scope;