AutoMapper 中嵌套对象的映射类型问题

mapping type Issue with nested objects in AutoMapper

使用 AutoMapper,我尝试在结果中显示带有评论数组的帖子列表。但是,作为 AutoMapper 的新手,我遇到了在显示的注释数组中包含不必要信息的问题。我尝试在PostDTO中使用CommentDTO,但在使用时出现映射类型错误。相反,我添加了另一个 CreateMap,但它在 PostDTO 中不起作用。你能告诉我如何处理这个问题吗?

型号

// post
   public class Post
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public int EmployeeId { get; set; }
        public Employee Employee { get; set; }

        public IList<Comment> Comments { get; set; }
    }

// Comment
 public class Comment
    {
        [Key]
        public int Id { get; set; }
        public string text { get; set; }
        public int EmployeeId { get; set; }
        public int PostId { get; set; }

        public virtual Employee Employee { get; set; }
        public virtual Post Post { get; set; }
    }

DTO

// PostDTO
public class PostDTO
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Author { get; set; }
        public string OrgName { get; set; }

        [JsonPropertyName("comments")]
        public IList<Comment> Comments { get; set; }  
        // When using 'public IList<CommentDTO> Comments { get; set; }' it occurs an error.
    }

// CommentDTO
 public class CommentDTO
    {
        public int Id { get; set; }
        public string Text { get; set; }
        public int CommentAuthor { get; set; }
    }

映射配置文件

 public class MappingProfile : AutoMapper.Profile
    {
        public MappingProfile()
        {

            CreateMap<Organization, OrgDTO>();
            CreateMap<Employee, EmpDTO>()
                .ForMember(d => d.OrgName, o => o.MapFrom(e => e.Organization.Name))
                .ForMember(d => d.Name, o => o.MapFrom(e => e.Name))
                .ForMember(d => d.Posts, o => o.MapFrom(e => e.Posts));

            CreateMap<Comment, CommentDTO>()
                .ForMember(d => d.CommentAuthor, o => o.MapFrom(c => c.Employee.Name))
                .ForMember(d => d.Text, o=>o.MapFrom(c =>c.text));

            CreateMap<Post, PostDTO>()
                .ForMember(d => d.Author, o => o.MapFrom(p => p.Employee.Name))
                .ForMember(d => d.OrgName, o => o.MapFrom(p => p.Employee.Organization.Name));
        }
    }

服务

public List<PostDTO> GetAllPosts()
        {
            var posts = _context.Posts
                .Include(x => x.Employee)
                .ThenInclude(x => x.Organization)
                .Include(x =>x.Comments)
                .ToList();
            List<PostDTO> result = _mapper.Map<List<Post>, List<PostDTO>>(posts);

            return result;
        }

实际结果

[
  {
    "id": 1,
    "title": "Test1",
    "author": "Tom",
    "orgName": "A",
    "comments": [
      {
        "id": 1,
        "text": "Good",
        "employeeId": 1,
        "postId": 1,
        "employee": {
          "id": 1,
          "name": "Tom",
          "organizationId": 1,
          "organization": {
            "id": 1,
            "name": "A",
            "employees": [
              {
                "id": 2,
                "name": "Kevin",
                "organizationId": 1,
                "posts": [
                  {
                    "id": 4,
                    "title": "Test4",
                    "employeeId": 2,
                    "comments": []
                  }
                ],
                "comments": [
                  {
                    "id": 2,
                    "text": "Bad",
                    "employeeId": 2,
                    "postId": 1,
                    "post": {
                      "id": 1,
                      "title": "Test1",
                      "employeeId": 1,
                      "comments": []
                    }
                  }
                ]
              }
            ]
          },
          "posts": [
            {
              "id": 1,
              "title": "Test1",
              "employeeId": 1,
              "comments": [
                {
                  "id": 2,
                  "text": "Bad",
                  "employeeId": 2,
                  "postId": 1,
                  "employee": {
                    "id": 2,
                    "name": "Kevin",
                    "organizationId": 1,
                    "organization": {
                      "id": 1,
                      "name": "A",
                      "employees": []
                    },
                    "posts": [
                      {
                        "id": 4,
                        "title": "Test4",
                        "employeeId": 2,
                        "comments": []
                      }
                    ],
                    "comments": []
                  }
                }
              ]
            .....

预期结果

[
  {
    "id": 1,
    "title": "Test1",
    "author": "Tom",
    "orgName": "A",
    "comments": [
      {
       "id": 1,
       "Text": "Nicee",
       "CommentAuthor": "Kevin"
      },
    ]
   },
...

错误

AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
List`1 -> List`1
System.Collections.Generic.List`1[[Persistence.Models.Post, Persistence, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] -> System.Collections.Generic.List`1[[Application.DTO.PostDTO, Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
 ---> AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
Post -> PostDTO
Persistence.Models.Post -> Application.DTO.PostDTO

Type Map configuration:
Post -> PostDTO
Persistence.Models.Post -> Application.DTO.PostDTO

Destination Member:
Comments

 ---> AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
IList`1 -> IList`1
System.Collections.Generic.IList`1[[Persistence.Models.Comment, Persistence, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] -> System.Collections.Generic.IList`1[[Application.DTO.CommentDTO, Application, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
 ---> AutoMapper.AutoMapperMappingException: Error mapping types.

Mapping types:
Comment -> CommentDTO
Persistence.Models.Comment -> Application.DTO.CommentDTO

Type Map configuration:
Comment -> CommentDTO
Persistence.Models.Comment -> Application.DTO.CommentDTO

Destination Member:
CommentAuthor

 ---> System.FormatException: Input string was not in a correct format.
   at System.Number.ThrowOverflowOrFormatException(ParsingStatus status, TypeCode type)
   at lambda_method(Closure , IList`1 , IList`1 , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method(Closure , IList`1 , IList`1 , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method(Closure , IList`1 , IList`1 , ResolutionContext )
   at lambda_method(Closure , List`1 , List`1 , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method(Closure , List`1 , List`1 , ResolutionContext )
   --- End of inner exception stack trace ---
   at lambda_method(Closure , List`1 , List`1 , ResolutionContext )
   at Application.Services.GetAllPosts() in C:\Users\sbaek\Documents\Dev\.NET Core LINQ_2106050605\Application\Services.cs:line 32
   at WebAPI.Controllers.BlogController.GetAllPost() in C:\Users\sbaek\Documents\Dev\.NET Core LINQ_2106050605\WebAPI\Controllers\BlogController.cs:line 26
   at lambda_method(Closure , Object , Object[] )
   at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
   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()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at NSwag.AspNetCore.Middlewares.SwaggerUiIndexMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.RedirectToIndexMiddleware.Invoke(HttpContext context)
   at NSwag.AspNetCore.Middlewares.OpenApiDocumentMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)


你的 CommentDTO 有一个 属性 int CommentAuthor 映射自 Employee.Name,我假设它是 string。听起来您需要将 CommentAuthor 设为 string