Can Automapper use an entity's navigation properties to pull values from related entities

automapper c# dto entity-framework-6 linq-to-entities

Question

Is Automapper able to drill down into an entityy navigation properties to map to a DTO class? Below is what I am doing to map results from an Entity Framework query to a DTO:

          public List<ProductRequestDetailDto> GetProductRequestExtendedDetailAll()
        {      
List<ProductRequest> aProductRequestList = unitOfWork.getProductRequestRepository().GetProductRequestExtendedDetailAll();

        List<ProductRequestDetailDto> ProductRequestDetailDtoList = new List<ProductRequestDetailDto>();

        foreach (ProductRequest Req in aProductRequestList)
        {
            ProductRequestDetailDto ProdReqDetDto = new ProductRequestDetailDto();
            ProdReqDetDto.ProductRequestId = Req.ProductRequestId;
            ProdReqDetDto.FirstName = Req.Employee.FirstName;
            ProdReqDetDto.MiddleInitial = Req.Employee.MiddleInitial;
            ProdReqDetDto.LastName = Req.Employee.LastName;
            ProdReqDetDto.DeptName = Req.Employee.Department.DeptName;
            ProdReqDetDto.DeviceType = Req.ProductProfile.DeviceType;
            ProdReqDetDto.ProductName = Req.ProductProfile.ProductName;
            ProdReqDetDto.ProductId = Req.ProductProfile.ProductId;
            ProdReqDetDto.ProductRequestStageId = Req.ProductRequestStage.ProductRequestStageId;
            ProdReqDetDto.DateRequested = Req.DateRequested;
            ProdReqDetDto.DateCompleted = Req.DateCompleted;
            ProdReqDetDto.SerialNumber = Req.SerialNumber;
            ProdReqDetDto.PhoneNumber = Req.PhoneNumber;

            ProductRequestDetailDtoList.Add(ProdReqDetDto);
        }

        return ProductRequestDetailDtoList;

    public List<ProductRequest> GetProductRequestExtendedDetailAll()
    {
        var ReportResult = from Req in context.ProductRequests
                           select Req;

        return ReportResult.ToList();
    }

I would like to avoid doing the above if Automapper can do it for me. Automapper has been able to map results to my DTOs when I don't need to drill down to the navigation properties of an entity which leads to other entities. I tried the following but it did not work probably because I need information that requires navigating to other entities such as Employee, Department, and ProductProfile:

    List<ProductRequestDetailDto> ProductRequestDetailDtoList = Mapper.Map<List<ProductRequestDetailDto>>(aProductRequestList);

If this can be done what is the correct way to do it?

1
1
1/12/2016 11:48:45 PM

Popular Answer

No, it cannot drill down into the properties because it cannot know how deep it should get or what to do with ambiguities.

By default it only maps automatically the properties with the same name, so this would already save you some code there but you would still need to teach it how to map the other properties. It can also map a list to another if the types they hold have a mapping to each other (which would remove the need for a foreach loop).

Note that if the properties with the same name don't have the same type you will also need to add a mapping for them (if they are not castable to each other).

public List<ProductRequestDetailDto> GetProductRequestExtendedDetailAll()
{    
    AutoMapper.Mapper.CreateMap<ProductRequest, ProductRequestDetailDto>()
        .ForMember(dest => dest.FirstName, opt => opt.MapFrom(src => src.Employee.FirstName))
        .ForMember(dest => dest.MiddleInitial, opt => opt.MapFrom(src => src.Employee.MiddleInitial))
        .ForMember(dest => dest.LastName, opt => opt.MapFrom(src => src.Employee.LastName))
        .ForMember(dest => dest.DeptName, opt => opt.MapFrom(src => src.Employee.Department.DeptName))
        .ForMember(dest => dest.DeviceType, opt => opt.MapFrom(src => src.ProductProfile.DeviceType))
        .ForMember(dest => dest.ProductName, opt => opt.MapFrom(src => src.ProductProfile.ProductName))
        .ForMember(dest => dest.ProductId, opt => opt.MapFrom(src => src.ProductProfile.ProductId))
        .ForMember(dest => dest.ProductRequestStageId, opt => opt.MapFrom(src => src.ProductRequestStage.ProductRequestStageId));

    IQueryable<ProductRequest> aProductRequestList = unitOfWork.getProductRequestRepository().GetProductRequestExtendedDetailAll();

    List<ProductRequestDetailDto> ProductRequestDetailDtoList = aProductRequestList.ProjectTo<ProductRequestDetailDto>().ToList();

    // or also
    // List<ProductRequestDetailDto> ProductRequestDetailDtoList = aProductRequestList.Select(AutoMapper.Mapper.Map<ProductRequestDetailDto>).ToList();

    return ProductRequestDetailDtoList;
}

public IQueryable<ProductRequest> GetProductRequestExtendedDetailAll()
{
    var ReportResult = from Req in context.ProductRequests
                       select Req;

    return ReportResult;
}
1
1/13/2016 12:27:20 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow