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
。
使用 AutoMapper,我尝试在结果中显示带有评论数组的帖子列表。但是,作为 AutoMapper 的新手,我遇到了在显示的注释数组中包含不必要信息的问题。我尝试在PostDTO中使用CommentDTO,但在使用时出现映射类型错误。相反,我添加了另一个 CreateMap
型号
// 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
。