frc frc - 29 days ago 5
C# Question

Pass a column value to model from a different table based on foreign key id

I have a

products
table which has a
CategoryId
which represents the respective primary key from the
Categories
table.

ProductViewModel

public ProductVM(ProductDTO productDTO)
{
Id = productDTO.Id;
Name = productDTO.Name;
Description = productDTO.Description;
Price = productDTO.Price;
CategoryId = productDTO.CategoryId;
ImageName = productDTO.ImageName;
}

public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }

public int? CategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public string ImageName { get; set; }
public IEnumerable<string> GalleryImages { get; set; }


Product DTO

public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }

[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}


This is how I get a list of products:

List<ProductVM> productVM;
using (Db db = new Db())
{
productVM = db.Products
.ToArray()
.Select(x => new ProductVM(x))
.ToList();
}


As you can see I am passing the
CategoryId
around and I can display it in my views with the
ProductVM
ViewModel, but I also want to get the
Name
of the category in there as well.

I can think of some hacks, e.g. accessing the
DB
from the constructor in the
ViewModel
based on the
CategoryId
and assigning it that way, but I wanna see if there is a more elegant solution?

Bottom line - I have a
Name
column in my
Categories
table and I want to pass that name to the
ProductVM
in a most effective way.

Answer

Add a property to you model for the category name, say

public string CategoryName { get; set; }

and modify the constructor to populate it

public ProductVM(ProductDTO productDTO)
{
    CategoryName  = productDTO.Category.Name;
    ....

and modify the query to

List<ProductVM> productVM = db.Products.AsEnumerable().Include(x => x.Category)
    .Select(x => new ProductVM(x)).ToList();

Note that you view model also required a parameterless constructor if your using this for editing otherwise an exception will be thrown in the POST method.

Note also that you do not need the using (Db db = new Db())