在 EF Core 5 中保存相关数据(多对多)而不获取实际记录

Save Related Data (Many to Many) in EF Core 5 without getting the actual records

我正在为午餐预订创建一个网络应用程序。

  public class Food : BaseEntity
    {
        public int FoodId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public string Ingredients { get; set; }
        public string PhotoPath { get; set; }
        public ICollection<Menu> Menus { get; set; }
        /*public ICollection<LunchReservation> LunchReservations { get; set; } omit */ 
    }
 public class Menu : BaseEntity
    {
        public Menu()
        {
            DateCreated = DateTimeOffset.Now;
            DateModified = DateTimeOffset.Now;
        }

        public int MenuId { get; set; }

        [Column(TypeName = "date")]
        public DateTime MenuDate { get; set; }
        public bool IsPublished { get; set; }
        public ICollection<Food> Foods { get; set; }
      /*public ICollection<LunchReservation> LunchReservations { get; set; } omit */ 

    }

一切正常,但是当我想创建一个可以包含 1 种或更多食物的菜单时,我收到错误消息。

这是我创建菜单的 Dto

  public class MenuCreationDto
    {
        public int[] FoodIds { get; set; }
        public string MenuDate { get; set; }
    }

此代码无法保存。

var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();
Menu newMenu = new()
{
 MenuDate = menuDateInGregorian,
 Foods = foods
};

await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();

但是为了节省食物,这段代码是有效的,但我不想从数据库中获取食物来制作菜单。

var foods = _db.Foods.Where(f => menuCDto.FoodIds.Contains(f.FoodId)).ToList();
Menu newMenu = new()
{
 MenuDate = menuDateInGregorian,
 Foods = foods
};
await _db.Menus.AddAsync(newMenu);
await _db.SaveChangesAsync();

如何在不从数据库中获取实际食物的情况下将菜单保存到数据库?

您可以像在您的非工作示例中那样使用伪造的(a.k.a.stub)实体

var foods = menuCDto.FoodIds.Select(f => new Food() { FoodId = f }).ToList();

但在让 EF Core 添加父实体 (Menu) 之前,您必须让它知道这些是“现有”实体,否则它将把它们视为“新”实体并尝试插入新 Food 条记录,而不是预期的链接。您可以通过将它们附加到上下文来做到这一点,这会将它们标记为已存在且未更改:

_db.AttachRange(foods);

其余代码将相同,但现在应该可以正常工作了。