Сохраните связанные данные (многие ко многим) в EF Core 5 без получения фактических записей

#c# #entity-framework-core #many-to-many #ef-core-5.0

#c# #entity-framework-core #многие ко многим #ef-core-5.0

Вопрос:

Я создаю веб-приложение для бронирования обеда.

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

что я могу сделать для сохранения меню в базе данных без получения фактических продуктов из базы данных?

Комментарии:

1. Я получаю ошибку — пожалуйста, всегда показывайте полный тип ошибки сообщение и где именно оно происходит. Это поможет вам получить точные ответы, а будущие посетители смогут найти ваш вопрос, если у них будет такая же ошибка.

2. Пожалуйста. Также было бы здорово сделать это на самом деле. Больше людей обнаружат эти вопросы и ответы (и, возможно, даже проголосуют).

Ответ №1:

Вы можете использовать поддельные (также известные как заглушки) объекты, как в вашем нерабочем примере

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

Но прежде чем позволить EF Core добавить родительский объект ( Menu ), вы должны сообщить ему, что это «существующие» объекты, в противном случае он будет рассматривать их как «новые» и попытается вставить новые Food записи, а не ссылки, как предполагалось. Вы делаете это, прикрепляя их к контексту, который помечает их как существующие и неизмененные:

 _db.AttachRange(foods);
 

Остальная часть кода будет такой же, но теперь должна работать.