AutoMapper: Expression mapping with flattening in collection
flobernd opened this issue · 3 comments
Hey there,
I'm currently playing around with Automapper.Expressions.ExpressionMapping and stumbled across an issue. These are the involved classes of my problematic entity:
public class MyDto
{
public Guid Id { get; set; }
public ICollection<string> Tags { get; set; }
}
public class MyEntity
{
public Guid Id { get; set; }
public ICollection<MyEntityTag> Tags { get; set; } // <- one-to-many relation
}
public class MyEntityTag
{
public Guid Id { get; set; }
public string Tag { get; set; }
}
As you see, the Tags collection from the entity is flattened from an object collection to just a string collection. For object mapping this works fine.
When using expression mapping and using the resulting expression with EntityFramework the following works as well:
x => x.Where(x => x.Tags.Any())
Sadly, the following does not work:
// Boolean Contains(System.String) can not be called with an instance of type MyEntityTag
x => x.Where(x => x.Tags.Contains("test"))
// Binary operator Equal is not defined for MyEntityTag and System.String
x => x.Where(x => x.Tags.Any(x => x == "test"))
I ofc understand what's going on, but I'm wondering if there is a way to tell AutoMapper how to correctly translate the expressions.
Best regards
You haven't included your configuration so hard to tell.
x => x.Where(x => x.Tags.Any(x => x == "test"))
should work with the following:
CreateMap<MyEntity, MyDto>()
.ForMember(dest => dest.Tags, opts => opts.MapFrom(src => src.Tags.Select(et => et.Tag)));
x => x.Where(x => x.Tags.Contains("test"))
needs the ToList()
to map the expression. i.e.
CreateMap<MyEntity, MyDto>()
.ForMember(dest => dest.Tags, opts => opts.MapFrom(src => src.Tags.Select(et => et.Tag).ToList()));
Or x => x.Where(x => x.Tags.Contains<string>("test"))
without ToList()
to get IEnumerable<string>.Contains()
.
Thanks for the fast reply!
You are right, I forgot to add my configuration - your first example looks pretty similar to my config. I will test again (especially with the additional .ToList()
) and reply back to you afterwards. If it's still not working I will construct a PoC configuration and include it in my response as well.
The .ToList()
makes the difference! Works like a charm now. Thanks again.