Search code examples
c#.net-coreasp.net-core-webapiautomapperrepository-pattern

Facing Issue on Mapping Parent Child Relation Table using Automapper in C#


--------------- PARENT MODEL CLASS ------------------------

public class TechCategory : AuditableBaseEntity
{
    public int TechCategoryId { get; set; }
    public string TechCategoryName { get; set; }
    public string Description { get; set; }
    public string Initial { get; set; }
    public virtual ICollection<TechSubcategory> TechSubCategories { get; set; }
}

---------------- CHILD MODEL CLASS ---------------------------

public class TechSubcategory : AuditableBaseEntity
{
public int TechSubcategoryId { get; set; }
public string TechSubcategoryName { get; set; }
public string Description { get; set; }
public string Initial { get; set; }
public int? TechCategoryId { get; set; }
public virtual TechCategory TechCategory { get; set; }
}

--------------------- DTO CLASS -------------------------------

public class TechSubCategoryDto
{
public int TechSubcategoryId { get; set; }
public string TechSubcategoryName { get; set; }
public string Description { get; set; }
public string Initial { get; set; }
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ModifiedDate { get; set; }
}

----------------------- MAPPER CLASS --------------------------

public class AutoMapperConfig: Profile
{
    public AutoMapperConfig()
    {
        CreateMap<TechCategory, TechCategoryDto>().ReverseMap();
        CreateMap<TechSubcategory, TechSubCategoryDto\>()
        .ForMember(x => x.CategoryId, opt => opt.MapFrom(x => x.TechCategoryId))
        .ForMember(x => x.CategoryName, opt => opt.MapFrom(x => x.TechCategory.TechCategoryName))
        .ReverseMap();
    }
}

------------------------ CONTROLLER CLASS ----------------------

[HttpGet]
[Route("All", Name = "GetAllSubCategory")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async Task<ActionResult<IEnumerable<TechSubCategoryDto>>> GetSubCategoryAsync()
{
var subCat = await _subCategoryRepository.GetAllAsync();
var catDto = _mapper.Map<List<TechSubCategoryDto>>(subCat);
return Ok(catDto);
}

Here is my output screen in swagger

It maps only [categoryId] but does not map the [categoryName], only null showing in [categoryname]

Please help to resolve the issue... enter image description here


Solution

  • The issue is not related to Automapper. The _subCategoryRepository.GetAllAsync() method will not fetch parent model "TechCategory" until you explicitly specify it while executing database query using entity framework core.

    Refer eager-loading in ef-core from here

    If you want to get values of "TechCategory" model while fetching "TechSubCategory" model. You need to create a method in your TechSubCategory Repositiory as following:

    Repository

    public async IEnumerable<TechSubCategory> GetAllIncludeTechCategoryAsync()
    {
        return await _dbContext.TechSubCategory.Include(x => x.TechCategory).ToListAsync();
    }
    

    Controller

    [HttpGet]
    [Route("All", Name = "GetAllSubCategory")]
    [ProducesResponseType(StatusCodes.Status200OK)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status404NotFound)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<ActionResult<IEnumerable<TechSubCategoryDto>>> GetSubCategoryAsync()
    {
        var subCat = await _subCategoryRepository.GetAllIncludeTechCategoryAsync();
        var catDto = _mapper.Map<List<TechSubCategoryDto>>(subCat);
        return Ok(catDto);
    }