我在应用程序中插入派生类型的警报时遇到问题。我有一个基类
Alert
及其相应的 DTO,以及一个派生类 OperationalAlert
(它扩展了 Alert
)和一个 OperationalAlertDto
。插入由 AlertTypeId
识别。但是,当我尝试插入 OperationalAlert
的实例时,这些值将显示为 null。我已确认所有属性都已正确映射到我的 AutoMapper 配置中,并且 DTO 和 OperationalAlertDto
中的必要字段均已填充。尽管如此,插入仍然失败。有没有人遇到过类似的问题或可以提供如何解决此问题的指导?
public async Task<Alert> CreateAlertAsync(AlertDTO alertDto)
{
if (alertDto == null)
{
throw new ArgumentNullException(nameof(alertDto), "Alert DTO cannot be null.");
}
Alert alert = alertDto.AlertTypeId switch
{
1 => _mapper.Map<AlertInformational>(alertDto) as Alert,
2 => _mapper.Map<AlertIncident>(alertDto) as Alert,
3 => _mapper.Map<OperationalAlert>(alertDto) as Alert,
4 => _mapper.Map<OperationalAlert>(alertDto) as Alert,
_ => throw new ArgumentOutOfRangeException(nameof(alertDto.AlertTypesId), "Invalid alert type"),
};
var addedAlertType = await _alertRepository.AddAsync(alert);
return addedAlertType;
}
这是错误跟踪:
public class Alert
{
public int Id { get; set; }
public int AlertTypeId{ get; set; }
public int CreatorId { get; set; }
public string Name { get; set; }
public string Title { get; set; }
public int TemplateRefId { get; set; }
public int DepartmentId { get; set; }
public bool IsProcessChanged { get; set; }
public bool? IsPermanent { get; set; }
public virtual Department? Department { get; set; }
public virtual User? Creator { get; set; }
public virtual AlertType? Type { get; set; }
public virtual Template? Template { get; set; }
public int ChangeDetailId { get; set; }
public virtual ChangeDetail? ChangeDetail { get; set; }
public virtual ICollection<Recipient>? AlertRecipients { get; set; }
public virtual ICollection<Attachment>? AlertAttachments { get; set; }
public virtual ICollection<Update>? AlertUpdates { get; set; }
public virtual ICollection<CustomLog>? LogEntries { get; set; }
public virtual ICollection<OperationDetail>? OperationDetails { get; set; }
}
using System.Collections.Generic;
namespace YourNamespace.Alerting.Domain.Model.Dto
{
public class AlertDTO
{
public int Id { get; set; }
public int AlertTypeId { get; set; }
public int CreatorId { get; set; }
public string UserName { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int TemplateRefId { get; set; }
public int DepartmentId { get; set; }
public bool IsProcessChanged { get; set; }
public bool? IsPermanent { get; set; }
public virtual ICollection<RecipientDto>? Recipients { get; set; }
public virtual ICollection<UpdateDto>? Updates { get; set; }
public virtual ICollection<AttachmentDto>? Attachments { get; set; }
public virtual ICollection<OperationDto>? Operations { get; set; }
public virtual ICollection<LogDto>? Logs { get; set; }
public int ChangeDetailId { get; set; }
}
public class ChangeDetailDto
{
public int Id { get; set; }
public string Name { get; set; }
}
public class RecipientDto
{
public int AlertId { get; set; }
public int RecipientId { get; set; }
}
public class UpdateDto
{
public int Id { get; set; }
public string Message { get; set; }
public int AlertId { get; set; }
public int TypeId { get; set; }
}
}
public class OperationalAlert : Alert
{
public AlertState State { get; set; }
public UrgencyLevel Urgency { get; set; }
public bool IsEnabled { get; set; }
public DateTime CreatedOn { get; set; }
public string Content { get; set; }
public DateTime ExpiresOn { get; set; }
public string Location { get; set; }
public string MessageContent { get; set; }
public string Description { get; set; }
public DateTime OccurrenceTime { get; set; }
public string Method { get; set; }
public string Reason { get; set; }
public virtual ICollection<OperationalAlertRevision>? Revisions { get; set; }
}
public enum AlertState
{
Active,
Inactive,
Expired,
Pending,
Resolved
}
public enum UrgencyLevel
{
Low,
Medium,
High,
Critical
}
这是产品警报的 dto :
public class OperationalAlertDto : AlertDTO
{
public int Id { get; set; }
public string Title { get; set; }
public AlertState State { get; set; }
public UrgencyLevel Urgency { get; set; }
public bool IsEnabled { get; set; }
public string Content { get; set; }
public DateTime CreatedOn { get; set; }
public DateTime ExpiresOn { get; set; }
public string Description { get; set; }
public DateTime OccurrenceTime { get; set; }
public string Method { get; set; }
public string Reason { get; set; }
public string Location { get; set; }
public string MessageContent { get; set; }
public List<OperationalAlertRevisionDto>? Revisions { get; set; }
}
public class OperationalAlertRevisionDto
{
public int RevisionId { get; set; }
public bool IsCurrent { get; set; }
public int AlertId { get; set; }
public int AlertTypeId { get; set; }
}
public AutoMapperProfile()
{
CreateMap<Department, DepartmentDTO>().ReverseMap();
CreateMap<TemplateType, TemplateTypeDTO>().ReverseMap();
CreateMap<Template, TemplateDTO>().ReverseMap();
CreateMap<User, UserDTO>();
CreateMap<OperationalAlertDto, OperationalAlert>()
.IncludeBase<AlertDTO, Alert>();
CreateMap<AlertDTO, AlertInformational>();
CreateMap<AlertDTO, AlertIncident>();
CreateMap<AlertDTO, OperationalAlert>().ReverseMap();
CreateMap<OperationalAlertDto, OperationalAlert>().ReverseMap();
CreateMap<OperationalAlertDto, OperationalAlert>().ReverseMap();
CreateMap<Alert, AlertDTO>()
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.user != null ? src.user.UserName : null))
.Include<OperationalAlert, OperationalAlertDto>()
.ReverseMap();
CreateMap<AlertRecipient, AlertRecipientDto>().ReverseMap();
CreateMap<AlertUpdate, AlertUpdateDto>().ReverseMap();
}
这是我的鉴别器定义:
builder.Services.AddControllers()
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
options.SerializerSettings.Converters.Add(
JsonSubtypesConverterBuilder
.Of(typeof(Alert), nameof(Alert.AlertTypeId I))
.RegisterSubtype(typeof(AlertInformational), 1)
.RegisterSubtype(typeof(AlertIncident), 2)
.RegisterSubtype(typeof(OperationalAlert), 4)
.SerializeDiscriminatorProperty()
.Build());
});
options.UseAllOfToExtendReferenceSchemas();
options.UseAllOfForInheritance();
options.UseOneOfForPolymorphism();
options.SelectDiscriminatorNameUsing(type =>
{
return type.Name switch
{
nameof(Alert) => "AlertTypeId",
_ => null
};
});
这里是错误跟踪,表明值不能插入为空,这表明数据的映射没有被正确识别,导致值没有被插入。
Microsoft.EntityFrameworkCore.Update[10000]
An exception occurred in the database while saving changes for context type 'alertapp_Alerting.Persistence.Context.alertappAlertingDbContext'.
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> MySqlConnector.MySqlException (0x80004005): Column 'Content' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 894
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 37
at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 130
at MySqlConnector.MySqlDataReader.NextResultAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 90
at MySqlConnector.MySqlDataReader.NextResultAsync(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 49
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> MySqlConnector.MySqlException (0x80004005): Column 'Content' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 894
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 37
at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 130
at MySqlConnector.MySqlDataReader.NextResultAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 90
at MySqlConnector.MySqlDataReader.NextResultAsync(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 49
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: An error occurred while adding the alert and sending the email.
---> Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> MySqlConnector.MySqlException (0x80004005): Column 'Content' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 894
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 37
at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 130
at MySqlConnector.MySqlDataReader.NextResultAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 90
at MySqlConnector.MySqlDataReader.NextResultAsync(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 49
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at alertapp_Alerting.Persistence.Repositories.AlertRepository.AddAsync(Alert alert) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Persistence\Repositories\AlertRepository.cs:line 47
--- End of inner exception stack trace ---
at alertapp_Alerting.Persistence.Repositories.AlertRepository.AddAsync(Alert alert) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Persistence\Repositories\AlertRepository.cs:line 54
at alertapp_Alerting.Services.AlertService.CreateAlertAsync(AlertDTO alertDto) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Services\AlertService.cs:line 83
at alertapp_Alerting.Controllers.AlertController.CreateAlertWithFile(AlertDTO alert) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Controllers\AlertController.cs:line 52
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareImpl.<Invoke>g__Awaited|10_0(ExceptionHandlerMiddlewareImpl middleware, HttpContext context, Task task)
fail: alertapp_Alerting.Exceptions.GeneralExceptionHandler[0]
Something went wrong..
System.InvalidOperationException: An error occurred while adding the alert and sending the email.
---> Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while saving the entity changes. See the inner exception for details.
---> MySqlConnector.MySqlException (0x80004005): Column 'Content' cannot be null
at MySqlConnector.Core.ServerSession.ReceiveReplyAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/ServerSession.cs:line 894
at MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) in /_/src/MySqlConnector/Core/ResultSet.cs:line 37
at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 130
at MySqlConnector.MySqlDataReader.NextResultAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 90
at MySqlConnector.MySqlDataReader.NextResultAsync(CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 49
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at alertapp_Alerting.Persistence.Repositories.AlertRepository.AddAsync(Alert alert) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Persistence\Repositories\AlertRepository.cs:line 47
--- End of inner exception stack trace ---
at alertapp_Alerting.Persistence.Repositories.AlertRepository.AddAsync(Alert alert) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Persistence\Repositories\AlertRepository.cs:line 54
at alertapp_Alerting.Services.AlertService.CreateAlertAsync(AlertDTO alertDto) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Services\AlertService.cs:line 83
at alertapp_Alerting.Controllers.AlertController.CreateAlertWithFile(AlertDTO alert) in C:\Users\e10133604\Desktop\alertappalertingapi\alertapp-Alerting\Controllers\AlertController.cs:line 52
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(ActionContext actionContext, IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|20_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
问题在于当您想要多态参数时控制器操作如何从请求填充模型。通常,如果您有一个接受基类 AlertDTO 的函数,并且您的调用代码构造了一个 OperationalAlertDTO、ProductionAlertDTO 或任何其他子类,并且您调用接受参数作为 AlertDTO 的方法,则该代码将按您的预期工作,因为底层对象“是一个”OperationalAlertDTO 等。因此,重新转换为子类的条件代码将起作用。对于多态方法来说,使用条件代码来处理特定的子类并不是一个好的实现,但是代码会按照您的预期工作。
但是,对于控制器操作,这将不起作用。当您创建接受 ActionDTO 的控制器操作时,如果该操作接受 ActionDTO,则对控制器的视图(表单或 Ajax/Fetch)调用是否填充足够的字段来创建 OperationalAlertDTO 或任何其他子类并不重要。 ActionDTO 控制器将仅尝试创建和填充 ActionDTO,而不是任何子类。
控制器操作有两个选项,具体取决于您构建应用程序的方式。如果您的视图等特定于警报类型,因此您的视图希望与 OperationalAlertDTO 一起使用,而不是与 ProductionAlertDTO 一起使用的其他视图,那么一个简单的解决方案是按具体子类类型拆分控制器操作,因为您正在有条件地处理示例中的每个子类。例如:
public async Task<Alert> CreateOperationalAlertAsync(OperationalAlertDTO alertDto)
public async Task<Alert> CreateProductionAlertAsync(ProductionAlertDTO alertDto)
然后,这些方法可以使用从 OperationalAlertDTO -> OperationalAlert 等正确的映射,不会出现问题,因为 MVC 会将从视图/客户端传递的任何数据解析为正确的具体 DTO 类型。
如果您希望对传入的这些警报的所有实例采取共同行为,您可以拥有一个共享私有函数,该函数接受来自每个警报的 AlertDto 作为
AlertDTO
,并且这些方法都可以调用该共享方法。只是避免将条件重铸放入常见的基类操作中。接受基类(或接口)的方法应该只关心每个调用的参数是该基类型。
另一种选择是连接自定义模型绑定器并在视图数据中公开具体类型,如下所示:
多态模型绑定和
带有列表
此方法允许使用OperationalAlertDTO 或ProductionAlertDTO 填充视图,从而公开具体类型的隐藏输入。自定义模型绑定程序在 ASP.Net MVC 中注册,以便当它具有需要 AlertDTO 类型的控制器方法时,它会在视图数据中查找 ModelType 并使用它来构造适当的具体子类。