Home > Enterprise >  Automapper nested mappings and grouping
Automapper nested mappings and grouping

Time:09-17

I'd like to get list of tasks grouped by TaskHead with list of tasks inside.

TaskItemToReturnHeadDTO.TaskHead == TaskItemToReturnDTO.ItemStage

Entity

    public class TaskItem
    {
        [Key]
        public int TaskItemId { get; set; }
        public string Name { get; set; }
        public string ItemStage { get; set; }
    }

DTOs

    public class TaskItemToReturnHeadDTO
    {
        public string TaskHead { get; set; }
        public ICollection<TaskItemToReturnDTO> Tasks { get; set; }
    }
    public class TaskItemToReturnDTO
    {
        public int TaskItemId { get; set; }
        public string Name { get; set; }
        public string ItemStage { get; set; }
    }

Controller

        [HttpGet("all")]
        public async Task<ActionResult<ICollection<TaskItem>>> GetTasks()
        {
            var tasks = await _context.TaskItems.ToListAsync();
            var mappedTasks = _mapper.Map<IEnumerable<TaskItemToReturnHeadDTO>>(tasks);

            return Ok(mappedTasks);
        }

AutoMapper Profile

            CreateMap<TaskItem, TaskItemToReturnDTO>().ReverseMap();

            CreateMap<TaskItemToReturnHeadDTO, TaskItem>().ReverseMap()
                .ForMember(dto => dto.TaskHead, c => c.MapFrom(c => c.ItemStage))
                .ForMember(dto => dto.Tasks, c => c.MapFrom(c => new List<TaskItemToReturnDTO> { new TaskItemToReturnDTO
                {
                    TaskItemId = c.TaskItemId,
                    Name = c.Name,
                    ItemStage = c.ItemStage
                }}));

This is my current result, but the tasks are not grouped.

[
    {
        "taskHead": "Design done",
        "tasks": [
            {
                "taskItemId": 1,
                "name": "Issuing",
                "itemStage": "Design done"
            }
        ]
    },
    {
        "taskHead": "Design done",
        "tasks": [
            {
                "taskItemId": 2,
                "name": "Issuing",
                "itemStage": "Design done"
            }
        ]
    },
    {
        "taskHead": "Design being checked",
        "tasks": [
            {
                "taskItemId": 4,
                "name": "SF Joists",
                "itemStage": "Design being checked"
            }
        ]
    },
    {
        "taskHead": "Design being checked",
        "tasks": [
            {
                "taskItemId": 5,
                "name": "FF Joists",
                "itemStage": "Design being checked"
            }
        ]
    },
    {
        "taskHead": "Being issued",
        "tasks": [
            {
                "taskItemId": 6,
                "name": "Roof",
                "itemStage": "Being issued"
            }
        ]
    }
]

Below I have shown how it should look like. This is my goal.

[
    {
        "taskHead": "Design done",
        "tasks": [
            {
                "taskItemId": 1,
                "name": "Issuing",
                "itemStage": "Design done"
            },
          {
                "taskItemId": 2,
                "name": "Issuing",
                "itemStage": "Design done"
            }
        ]
    },
    {
        "taskHead": "Design being checked",
        "tasks": [
            {
                "taskItemId": 4,
                "name": "SF Joists",
                "itemStage": "Design being checked"
            },
          {
                "taskItemId": 5,
                "name": "FF Joists",
                "itemStage": "Design being checked"
            }
        ]
    },
    {
        "taskHead": "Being issued",
        "tasks": [
            {
                "taskItemId": 6,
                "name": "Roof",
                "itemStage": "Being issued"

            }
        ]
    }
]

I think I should use GroupBy function somewhere but I cant figure out where and how. Maybe I have wrong mapping?

CodePudding user response:

Automapper works fine for TaskItemToReturnDTO, but you don't need to crate a mapper for TaskItemToReturnHeadDTO. Instead, use linq for grouping after mapping as follows:

var mappedTasks = _mapper.Map<IEnumerable<TaskItemToReturnDTO>>(tasks);
var groupedTasks = mappedTasks
    .GroupBy(task => task.ItemStage)
    .Select(group => new TaskItemToReturnHeadDTO { TaskHead = group.Key, Tasks = group.ToList() });

CodePudding user response:

@Oignon_Rouge Thank you, already figured out with pretty similar code... can you check if my version is okay? Works fine for me :)

        [HttpGet("all")]
        public async Task<ActionResult<ICollection<TaskItem>>> GetTasks()
        {
            var tasks = await _context.TaskItems.ToListAsync();
            var mappedTasks = _mapper.Map<IEnumerable<TaskItemToReturnHeadDTO>>(tasks);

            var groupedTasks = mappedTasks.GroupBy(z => z.TaskHead).Select(v => new TaskItemToReturnHeadDTO
            {
                TaskHead = v.Key,
                Tasks = _mapper.Map<ICollection<TaskItemToReturnDTO>>(tasks).Where(x => x.ItemStage == v.Key).ToList()
            });

            return Ok(groupedTasks);
        }
  • Related