Reputation: 75
I have a problem with many to many relationship in EF core. I have the following model classes:
public class Meal
{
public int Id { get; set; }
[Required]
public int Insulin { get; set; }
public MealType Type { get; set; }
public ICollection<MealFood> MealFoods { get; set; }
public Meal()
{
MealFoods = new Collection<MealFood>();
}
}
public class Food
{
public int Id { get; set; }
[StringLength(255)]
public string Name { get; set; }
[Required]
public int Carbohydrates { get; set; }
public ICollection<MealFood> MealFoods { get; set; }
public Food()
{
MealFoods = new Collection<MealFood>();
}
}
public class MealFood
{
public int MealId { get; set; }
public Meal Meal { get; set; }
public int FoodId { get; set; }
public Food Food { get; set; }
}
I have the following API resource class:
public class MealResource
{
public int Id { get; set; }
public int Insulin { get; set; }
public MealType Type { get; set; }
public ICollection<FoodResource> Foods { get; set; }
public MealResource()
{
Foods = new Collection<FoodResource>();
}
}
I have done the mapping in my DbContext:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<MealFood>().HasKey(mf => new { mf.MealId, mf.FoodId });
modelBuilder.Entity<MealFood>().HasOne(mf => mf.Meal).WithMany(m => m.MealFoods).HasForeignKey(mf => mf.MealId);
modelBuilder.Entity<MealFood>().HasOne(mf => mf.Food).WithMany(f => f.MealFoods).HasForeignKey(mf => mf.FoodId);
}
I've got a problem with this call:
var meals = await context.Meals.Include(m => m.MealFoods).ToListAsync();
This returns almost everything I need, except the navigation properties from MealFoods
The reason why I want those properties, because I want to do the following mapping:
CreateMap<Meal, MealResource>().ForMember(mr => mr.Foods, opt => opt.MapFrom(x => x.MealFoods.Select(y => y.Food).ToList()));
I have already found this: Automapper many to many mapping
but (maybe I don't get something) this doesn't work because the property called Food in MealFood is null.
I hope I didn't explain too complex.
Upvotes: 1
Views: 1891
Reputation: 205539
When you include navigation property, EF Core automatically fills the inverse navigation property, e.g. including Meal.MealFoods
will automatically fill MealFood.Meal
, including Food.MealFoods
will automatically populate MealFood.Food
etc. In order to populate other navigation properties you need to use additional ThenInclude
. E.g.
var meals = await context.Meals
.Include(m => m.MealFoods)
.ThenInclude(mf => mf.Food) // <--
.ToListAsync();
or
var foods = await context.Foods
.Include(f => f.MealFoods)
.ThenInclude(mf => mf.Meal) // <--
.ToListAsync();
Upvotes: 4