Многие ко многим грубым операциям в ядре asp.net

У меня есть два объекта (Product и Supply), которые имеют отношения «многие ко многим». У меня также есть объект между ними, который содержит два идентификатора (SupplyProduct).

Мои сущности:

    public class Product
    {
        [Key]
        public int ProductId { get; set; }
        [Required]
        public string? ProductName { get; set; }
        [Required]

        [Column(TypeName = "decimal(6,2)")]
        public decimal UnitPrice { get; set; }
        public int Quantity { get; set; }
        public string? Brand { get; set; }
        public DateTime CreatedDateTime { get; set; } = DateTime.Now;

        //Many to many relationship between the products and the stocks
        public virtual ICollection<SupplyProduct>? SupplyProducts { get; set; }
    }

    public class Supply
    {
        [Key]
        [Required]
        public int SupplyId { get; set; }
        [Required]

        [DisplayName("Supply's Label")]
        public string? Label { get; set; }
        
        //One to many relationship between the Stock and the Merchant
        public Merchant? Merchant { get; set; }

        //Many to many relationship between the stocks and the products
        public virtual ICollection<SupplyProduct>? SupplyProducts { get; set; }

    }

    public class SupplyProduct
    {
        [Key]
        public int SupplyId { get; set; }
        public virtual Supply? Supply { get; set; }
        [Key]
        public int ProductId { get; set; }
        public virtual Product? Product { get; set; }
    }

Я хочу назначить поставку продукту при его создании. а затем показать поставку с сопутствующими продуктами

это мой контроллер продуктов:

ПродуктыController.cs

public class ProductController : Controller
    {
        private readonly ApplicationDbContext _db;

        public ProductController(ApplicationDbContext db)
        {
            _db = db;
        }

        // GET: ProductController
        public ActionResult Index()
        {
            IEnumerable<Product> ProductsList = _db.Products;
            return View(ProductsList);
        }

        // GET: ProductController/Create
        public ActionResult Create()
        {
            IEnumerable<Supply> SuppliesList = _db.Supplies.Include(s => s.Merchant);
            ViewBag.Supplies = SuppliesList;
            return View();
        }

        // POST: ProductController/Create
        [HttpPost]
        public ActionResult Create(Product model, List<int> supplyIds)
        {
            _db.Products.Add(model);
            _db.SaveChanges();
            
            SupplyProduct SP = new();
            foreach (var supplyId in supplyIds)
            {
                SP.SupplyId = supplyId;
                SP.ProductId = model.ProductId;
                SP.Product = model;
                SP.Supply = _db.Supplies.Where(x => x.SupplyId == supplyId).FirstOrDefault();
            }
            _db.SupplyProducts.Add(SP);
            _db.SaveChanges();
            return RedirectToAction(nameof(Index));
        }
}

Не могли бы вы проверить метод моего поста Create, если он такой, каким он должен быть, и как я могу получить данные о продуктах при возврате расходных материалов в методе Index в представление индекса?

Большое спасибо за вашу помощь и счастливого кодирования: D

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
106
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете удалить вкладку SupplyProduct, если нет дополнительных свойств ни в чем, кроме Supply Product, который вам не нужен для многих-ко-многим. Затем инициализируйте коллекции в снабжении и продукте.

public class Product
{
    public Product()
    {
        this.Supplys = new HashSet<Supply>();
    }

    //... your props

    public virtual ICollection<Supply> Supplys { get; set; }
}

public class Supply
{
    public Supply()
    {
        this.Products = new HashSet<Product>();
    }

    //... your props

    public virtual ICollection<Product> Products { get; set; }
}

Добавьте продукт в поставку только с одним запросом (в вашем коде вы делаете запрос для каждого идентификатора в supplyIds)

[HttpPost]
public ActionResult Create(Product model, List<int> supplyIds)
{
     //Get all supplys you need by id
     var supplys = _db.Supplys
         .Where(x => supplyIds.Contains(x.SupplyId))
         .ToList();
     
     //Add product in each supply
     foreach (var supply in supplys)
     {
         supply.Products.Add(model);
     }

     //Update db
     _db.SaveChanges();

     return RedirectToAction(nameof(Index));
}

Получить из БД

public ActionResult GetSuplys(List<int> supplyIds)
{
     //Here you get all Supplys with the Products in it
     var supplys = _db.Supplys
         .Include(x => x.Products)
         .Where(x => supplyIds.Contains(x.SupplyId))
         .ToList();

     //...
}

Сохранить новую поставку продукта

public ActionResult NewSuply()
{

     var supply = new Supply
     {
        ProductName = name,
        //Add all props you need
        //You can add Product here or add empty collection
        Products.Add(product), or = new List<Product>();
     }
     
     //No need to save Product separate
     _db.Add(supply);
     _db.SaveChanges();
}
Ответ принят как подходящий

Не могли бы вы проверить мой метод создания сообщения, если он такой, каким должен быть?

Измените свой код, как показано ниже, иначе вы всегда будете хранить второй запас в supplyIds:

 [HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(Product model, List<int> supplyIds)
{
    _context.Product.Add(model);
    _context.SaveChanges();

    SupplyProduct SP = new();
    foreach (var supplyId in supplyIds)
    {
        SP.SupplyId = supplyId;
        SP.ProductId = model.ProductId;
        SP.Product = model;
        SP.Supply = _context.Supply.Where(x => x.SupplyId == supplyId).FirstOrDefault();
        _context.SupplyProducts.Add(SP);   //move to here...
        _context.SaveChanges();
    }
    // _context.SupplyProducts.Add(SP);
    //_context.SaveChanges();
    return RedirectToAction(nameof(Index));
}

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

Измените метод индекса, как показано ниже:

// GET: Products
public async Task<IActionResult> Index()
{
    var data = await _context.Product.Include(p => p.SupplyProducts)
                             .ThenInclude(sp => sp.Supply).ToListAsync();
    return View(data);
}

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