EF Core 中的多对多关系映射 [英] Many to many relationship mapping in EF Core

查看:47
本文介绍了EF Core 中的多对多关系映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 EF 核心中遇到多对多关系的问题.我有以下模型类:

公共课餐{公共 int Id { 获取;放;}[必需的]公共 int 胰岛素 { 得到;放;}公共膳食类型 { 获取;放;}公共 ICollection<MealFood>MealFoods { 得到;放;}公共餐(){MealFoods = 新系列();}}公共课食品{公共 int Id { 获取;放;}[字符串长度(255)]公共字符串名称 { 获取;放;}[必需的]公共整数碳水化合物{得到;放;}公共 ICollection<MealFood>MealFoods { 得到;放;}公共食品(){MealFoods = 新系列();}}公共课 MealFood{公共 int MealId { 获取;放;}公共餐餐{得到;放;}公共 int FoodId { 获取;放;}公共食品食品{得到;放;}}

我有以下 API 资源类:

公共类 MealResource{公共 int Id { 获取;放;}公共 int 胰岛素 { 得到;放;}公共膳食类型 { 获取;放;}公共 ICollection食物{得到;放;}公共膳食资源(){Foods = new Collection();}}

我已经在我的 DbContext 中完成了映射:

protected override void OnModelCreating(ModelBuilder modelBuilder){modelBuilder.Entity().HasKey(mf => new { mf.MealId, mf.FoodId });modelBuilder.Entity().HasOne(mf => mf.Meal).WithMany(m => m.MealFoods).HasForeignKey(mf => mf.MealId);modelBuilder.Entity().HasOne(mf => mf.Food).WithMany(f => f.MealFoods).HasForeignKey(mf => mf.FoodId);}

这个调用有问题:

var Meals = await context.Meals.Include(m => m.MealFoods).ToListAsync();

这将返回我需要的几乎所有内容,除了来自 MealFoods 的导航属性

之所以想要那些属性,是因为我想做如下映射:

CreateMap().ForMember(mr => mr.Foods, opt => opt.MapFrom(x => x.MealFoods.Select(y => y.Food)).ToList()));

我已经找到了:Automapper 多对多映射

但是(也许我没有得到一些东西)这不起作用,因为 MealFood 中名为 Food 的属性为空.

希望我没有解释得太复杂.

解决方案

当您包含导航属性时,EF Core 会自动填充反向导航属性,例如包括Meal.MealFoods会自动填充MealFood.Meal,包括Food.MealFoods会自动填充MealFood.Food等. 为了填充其他导航属性,您需要使用额外的 ThenInclude.例如

var Meals = await context.Meals.Include(m => m.MealFoods).ThenInclude(mf => mf.Food)//<--.ToListAsync();

var food = await context.Foods.include(f => f.MealFoods).ThenInclude(mf => mf.Meal)//<--.ToListAsync();

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.

解决方案

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();

这篇关于EF Core 中的多对多关系映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆