AutoMapper / AutoMapper.Extensions.OData

Creates LINQ expressions from ODataQueryOptions and executes the query.
MIT License
140 stars 38 forks source link

Requiring explicit mapping only when mapping OData queries #173

Closed AntonC9018 closed 1 year ago

AntonC9018 commented 1 year ago

Consider the following code:

public class A
{
    public string? Str { get; set; }
}

public class B
{
    public string? Str { get; set; }
}

class MyMapper : Profile
{
    public MyMapper()
    {
        CreateMap<A, B>()
            .ForAllMembers(o => o.ExplicitExpansion());
    }
}

[Fact]
public void Stuff()
{
    var config = new MapperConfiguration(configuration =>
    {
        configuration.AddProfile<MyMapper>();
    });
    var b1 = config.CreateMapper().Map<B>(new A { Str = "Hello" });

    var arr = new A[]
    {
        new A { Str = "1" },
        new A { Str = "2" },
    };
    var query = arr.AsQueryable();
    var b2 = query.ProjectTo<B>(config).ToList();
    var b3 = query.ProjectTo<B>(config, parameters: null, a => a.Str).ToList();
}

As required by the library, I'm using the ExplicitExpansion feature for all members. However, this has the side effect that when I project any queryable, it ends up without any members filled in, which is to be expected. So b2 ends up with nulls, because I haven't explicitly given it any expressions, while b3 gets that member filled it. Normal mapping (b1) also fills all members in.

This wouldn't be a problem if I didn't have to use the mapper outside of OData. If I'm using the projection simply, without mapping any members explicitly, I want it to fill in all members and behave as though ExplicitExpansion is never set, otherwise I would get nulls. To be clear, I need this behavior when doing other EF Core queries, unrelated to OData. An obvious solution would be to duplicate the dtos and the mapper logic, but it's clearly not optimal.

Is there any convenient option the library provides?

Looking at the public API I couldn't find anything useful easily, and I don't have the knowledge of the internals to dig deeper into the library code looking for clues.

BlaiseD commented 1 year ago

Not sure why you would need duplicate DTOs but multiple configurations should work. Maybe use DI or otherwise to inject/select a mapper with the right configuration.