0

I'm mapping select expression (projection) of Linq query. This is done to decouple logic layer from data access layer and logic layer should use only DTOs.

Expression<Func<CountyInfoDto, CountyInfoDto>> selector = c =>
new CountyInfoDto
{
    Id = c.Id,
    Citizens = c.Citizens.Select(p => new CitizenDto
    {
    }).ToList()
};

var resEx = mapper.MapExpression<Expression<Func<CountyInfo, CountyInfoDto>>>(selector);  

This mapping fails with error Expression of type 'DTOs.CitizenDto' cannot be used for return type 'Entities.Citizen' however in CountyInfoDto property Citizens has type CitizenDto. Please note all mapping profiles are valid and simple objects can be mapped properly.
If I do like this, all works:

Expression<Func<CountyInfoDto, CountyInfoDto>> selector = c =>
new CountyInfoDto
{
    Id = c.Id
};

var resEx = mapper.MapExpression<Expression<Func<CountyInfo, CountyInfoDto>>>(selector);

or this also works:

Expression<Func<CountyInfoDto, CountyInfoDto>> selector = c =>
new CountyInfoDto
{
    Id = c.Id,
    Citizens = new List<CitizenDto>
    {
        new CitizenDto
        {
            Id = c.Citizens.First().Id
        }
    }
};

var resEx = mapper.MapExpression<Expression<Func<CountyInfo, CountyInfoDto>>>(selector);  

is there any possibility to avoid this error?

Classes:

public class CountyInfo
{
    public CountyInfo()
    {
        Citizens = new HashSet<Citizen>();
    }

    public Guid Id { get; set; }

    public string Name { get; set; }

    public ICollection<Citizen> Citizens { get; set; }
}

public class Citizen
{
    public Guid Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string ZipCode { get; set; }
}

public class CountyInfoDto
{
    public CountyInfoDto()
    {
        Citizens = new List<CitizenDto>();
    }

    public Guid Id { get; set; }

    public string Name { get; set; }

    public List<CitizenDto> Citizens { get; set; }
}

public class CitizenDto
{
    public Guid Id { get; set; }

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public string ZipCode { get; set; }
}

Mappings:

CreateMap<CountyInfo, CountyInfoDto>().ReverseMap();
CreateMap<Citizen, CitizenDto>().ReverseMap();

I'm using AutoMapper.Extensions.ExpressionMapping, after update to latest version error is: No coercion operator is defined between types 'Entities.CountyInfo' and 'DTOs.CountyInfoDto'.

Alexey Klipilin
  • 1,866
  • 13
  • 29
  • Can you please add code for you classes and mapper configuration? – Guru Stron May 21 '20 at 07:47
  • @GuruStron I've added new info, please take a look. – Alexey Klipilin May 21 '20 at 08:29
  • BTW have you tried just `db.Counties.UseAsDataSource().For().Select(selector)`? Or it fails with the same exception? – Guru Stron May 21 '20 at 08:49
  • @GuruStron if I understand correctly after `For` I will be able to access only properties specified in `CountyInfoDto`, but in general I need to filter by any property in my Entity and select any another set of properties – Alexey Klipilin May 21 '20 at 08:59
  • You can apply your filtering before `UseAsDataSource()` as far as I understand. – Guru Stron May 21 '20 at 09:01
  • @GuruStron ok, but also as I understand if I do `For` that is going to include all navigation properties which are mapped there. But technically I need to expand only particular properties in this query and another set of navigation properties should be expanded in another query. To solve this issue I will have to create so many different DTOs for `For` projection however I want only to modify query – Alexey Klipilin May 21 '20 at 09:03
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/214321/discussion-between-guru-stron-and-alexey). – Guru Stron May 21 '20 at 09:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/214394/discussion-between-alexey-klipilin-and-guru-stron). – Alexey Klipilin May 22 '20 at 06:03

0 Answers0