Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OrderBy for properties in IQueryable Projection #1127

Open
johnwnowlin opened this issue Feb 22, 2024 · 3 comments
Open

OrderBy for properties in IQueryable Projection #1127

johnwnowlin opened this issue Feb 22, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@johnwnowlin
Copy link

johnwnowlin commented Feb 22, 2024

Is your feature request related to a problem? Please describe.

I would love to OrderBy a child list in a IQueryable projections map. The example I have is a list of counties for a particular state.

Describe the solution you'd like

Ability to add [OrderBy(nameof(Counties.Name))] maybe similar to current Constructor Mappings.

[Mapper]
public partial class TerritoryMapper : IMapper<TerritoryRequest, Territory>
{
    [OrderBy(nameof(Counties.Name))]
    public partial IQueryable<TerritoryResponse> ToResponse(IQueryable<Territory> territory);
}

// Expected generated code
public partial class TerritoryMapper
{
    public partial global::System.Linq.IQueryable<global::RepData.Entities.Models.TerritoryResponse> ToResponse(global::System.Linq.IQueryable<global::RepData.Entities.Models.Territory> territory)
    {
#nullable disable
        return System.Linq.Queryable.Select(territory, x => new global::RepData.Entities.Models.TerritoryResponse()
        { 
               ...
        },
       Counties = global::System.Linq.Enumerable.ToList(global::System.Linq.Enumerable.Select(x.Counties, x1 => new global::RepData.Entities.Models.CountyResponse()
        {
            Id = x1.Id,
            Name = x1.Name,
        })
        .OrderBy(x2 => x2.Name)
 ),
 

Describe alternatives you've considered

After mapping I apply order by to the items. This requires another loop. Also does not let efcore know to apply order by to sql statements.

var mapper = new TerritoryMapper();
var response = await mapper.ToResponse(query)
    .ToArrayAsync();

foreach (var item in response)
{
    item.Counties = item.Counties
        .OrderBy(a => a.Name)
        .ToList();
}
@johnwnowlin johnwnowlin added the enhancement New feature or request label Feb 22, 2024
@latonz
Copy link
Contributor

latonz commented Feb 23, 2024

Thank you for opening this issue. Couldn't this be achieved by a combination of #783 and #863 by implementing a user-implemented mapping from IEnumerable<TSource> to IEnumerable<TTarget> which handles the ordering?

@johnwnowlin
Copy link
Author

Upgraded to Mapperley 3.4 and tried this

    [MapProperty(nameof(CountyResponse), nameof(TerritoryResponse.Counties))]
    public List<CountyResponse> OrderCounties(ICollection<County> counties) => counties.OrderBy(a => a.Name).ToList();

But that generates

}
Counties = OrderCounties(x.Counties),

Which is close, but requires that I add the new CountyResponse() { ... } into the MapProperty function.

[MapProperty(nameof(CountyResponse), nameof(TerritoryResponse.Counties))]
public List<CountyResponse> OrderCounties(ICollection<County> x) =>
    Enumerable.ToList(Enumerable.Select(x, x1 => new CountyResponse()
    {
        Id = x1.Id,
        Name = x1.Name,
    }))
    .OrderBy(a => a.Name)
    .ToList();

I tried several variations with less success.

If you see how to use the MapProperty function more accurately please guide me.

@latonz
Copy link
Contributor

latonz commented Feb 25, 2024

Oh #783 is not yet released and #863 is not yet implemented.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants