0

I'm using SQL Server 2012, MVC WebAPI, AutoMapper and Entity Framework. In the database I have two tables with one-to-many relation, for example Categories and Products; a category can have more products but a product can have only one category. What I want is a json that for each category contains also an array of related products by Products.CategoryId field.

This is what I made after some search in internet:

public class CategoriesViewModel
{
    public string CategoryName { get; set; }
    public IEnumerable<ProductsViewModel> Products { get; set; }
}

public class ProductsViewModel
{
    public string Name { get; set; }
}

public static class ViewModelMapper
{
    public static TDestination Map<TDestination>(object source)
    {
        return Mapper.Map<TDestination>(source);
    }

    public static void RegisterMaps()
    {
        AutoMapper.Mapper.Initialize(config =>
        {
            config.CreateMap<Products, ProductsViewModel>().ReverseMap();
            config.CreateMap<Categories, CategoriesViewModel>()
                .ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.Products))
                .ReverseMap();
        }
    }
}

// Repository
public IEnumerable<CategoriesViewModel> GetCategories()
{
    return ViewModelMapper.Map<IEnumerable<CategoriesViewModel>>(Context.Categories);
}

//Business Logic
public IEnumerable<CategoriesViewModel> GetCategories()
{
    return Repository.GetCategories();
}

[Route("Categories"), HttpGet]
public IHttpActionResult GetCategories()
{
    return Ok(BL.GetCategories());
}

My result is a list of Categories with and empty or null Products array and I cannot find a solution.

How can I reach my result? Thank you

EDIT:

Entity Framework Models

public partial class Category
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public Category()
    {
        this.Products = new HashSet<Product>();
    }

    public int CategoryId { get; set; }
    public string CategoryName { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<Product> Products { get; set; }
}

public partial class Product
{
    public int ProductId { get; set; }
    public int CategoryId { get; set; }
    public string ProductName { get; set; }

    public virtual Category Category { get; set; }
}

Category and Product are only examples, ignore if the view model property names are not the same.

chenny
  • 769
  • 2
  • 17
  • 44
  • Can we see the models? – Ivan Stoev Nov 10 '16 at 18:35
  • I think that there is a misunderstanding with class names. Classes as CategoriesViewModel are Models. I don't have any other type of code: CategoriesRepository gets data from database by EF and returns mapped CategoriesViewModel. – chenny Nov 10 '16 at 19:06
  • No, they are the ViewModels and are irrelevant to the issue. I need the entity models, i.e. `Categories` and `Products` classes. – Ivan Stoev Nov 10 '16 at 19:08
  • Do you mean EF generated classes? I added them. – chenny Nov 10 '16 at 19:53

1 Answers1

1

I suspect you have Lazy Loading off.

So one solution would be to turn it on, but I would not suggest it, because it would execute many database queries.

A better option would be to use Eager Loading:

return ViewModelMapper.Map<IEnumerable<CategoriesViewModel>>(
    Context.Categories.Include(c => c.Products));

or

return ViewModelMapper.Map<IEnumerable<CategoriesViewModel>>(
    Context.Categories.Include("Products"));

But the best option with AutoMapper is to use ProjectTo method from QueryableExtensions:

retirn Context.Categories.ProjectTo<CategoriesViewModel>();

for the reasons explained in the link.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
  • It would be nice if you provide some feedback, like does the answer helped resolving the issue or not etc. – Ivan Stoev Nov 11 '16 at 09:04
  • Sure, sorry but I've just tested it now at work. It works great the suggestions with AutoMapper extension for Entity Framework! ;) In my real case I had also some mapping problem with nullable properties so I fixed them. Thank you very much. – chenny Nov 11 '16 at 09:08