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

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

  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 ответ

Решение

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

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

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

_db.AttachRange(foods);

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

Другие вопросы по тегам