Skip to content

Support flattening collections #2253

@mhartmair-cubido

Description

@mhartmair-cubido

Is your feature request related to a problem? Please describe.
In EF Core, there are m:n-relation tables which are verbose to map.

Describe the solution you'd like
The flattening definition automatically handles collections on the way.

public class User
{
    public string Id { get; set; }

    public ICollection<UserRole> UserRoles { get; set; } = new List<UserRole>();
}

public class UserRole
{
    public int Id { get; set; }

    public int UserId { get; set; }
    public User User { get; set; } = null!;

    public int RoleId { get; set; }
    public Role Role { get; set; } = null!;
}

public class Role
{
    public int Id { get; set; }
    public required string Name { get; set; }

    public ICollection<UserRole> UserRoles { get; set; } = new List<UserRole>();
}

public class UserDto
{
    public int Id { get; set; }
    public List<RoleDto> Roles { get; set; } = [];
}

public class RoleDto
{
    public required string Name { get; set; };
}

[Mapper]
public static partial class UserDtoMapper
{
    public static partial RoleDto MapToRoleDto(Role src);

    // Expect this to do all the magic
    [MapProperty($"{nameof(src.UserRoles)}.{UserRole.Role}"), nameof(UserDto.Roles))]
    public static partial UserDto MapToUserDto(User src);
}

// Expected generated code
        [global::System.CodeDom.Compiler.GeneratedCode("Riok.Mapperly", "5.0.0.0")]
        public static partial global::System.Linq.IQueryable<global::ObjectMappers.Application.Users.Queries.GetUsers.UserDto> ProjectToUserDto(this global::System.Linq.IQueryable<global::ObjectMappers.Domain.Entities.User> src)
        {
#nullable disable
            return global::System.Linq.Queryable.Select(
                src,
                x => new global::ObjectMappers.Application.Users.Queries.GetUsers.UserDto()
                {
                    Id = x.Id,
                    Roles = global::System.Linq.Enumerable.ToList(
                        global::System.Linq.Enumerable.Select(
                            x.UserRoles,
                            x1 => new global::ObjectMappers.Application.Common.Models.RoleDto()
                            {
                                Id = x1.Role.Id,
                                Name = x1.Role.Name
                            }
                        )
                    ),
                }
            );
#nullable enable
        }

Describe alternatives you've considered
Define a user-defined mapping method by hand

    private static RoleDto Map(UserRole src) => MapRoleDto(src.Role);

    [MapProperty(nameof(src.UserRoles), nameof(UserDto.Roles))]
    public static partial UserDto MapToUserDto(User src);

Additional context

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions