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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions