Получение дубликатов при сохранении элемента с двумя полями в отношениях многие-ко-многим

Вопрос или проблема

Я работаю над проектом интернет-магазина. В проекте есть модель под названием Product, которая имеет отношение многих ко многим с моделью под названием Color через модель Product-Color. Я хочу добавить свойство под названием Quantity в Product-Color для каждого Color, который я добавляю. Я использую Razor Page и .net 8.

Вот что я уже сделал.

Это представление:

 <div class="form-group">
     <label>Цвета</label>
     @{
         var colors = ViewData["Colors"] as List<Color>;
     }
     @foreach (Color color in colors)
     {
         <div>
             <input type="checkbox" name="SelectedColors" value="@color.ColorId"/>@color.ColorName
             <div>
                 <label>Количество</label>
                 <input type="number" name="ColorQuantities" class="form-control" />
             </div>
             <hr/>
         </div>
     }
 </div>

Это код за страницей:

 public IActionResult OnPost(IFormFile imgProductUp, List<int> SelectedColors, List<int>? ColorQuantities)
 {
     if (!ModelState.IsValid)
     {
         return Page();
     }

     int productId = _productService.AddProduct(Product, imgProductUp);
     _productService.AddColorToProductByAdmin(productId, SelectedColors, ColorQuantities);
     return RedirectToPage("Index");
 }

Это сервис:

   public void AddColorToProductByAdmin(int productId, List<int>? SelectedColor, List<int>? ColorQuantities)
   {
       foreach (int color in SelectedColor)
       {
           foreach (int quantity in ColorQuantities)
           {
               _context.ProductColors.Add(new ProductColor()
               {
                   ProductId = productId,
                   ColorId = color,
                   Quantity = quantity
               });
           }
       }
       _context.SaveChanges();
   }

Я хочу назначить свойство “Quantity” для выбранного ColorId в таблице Product-Color, но мои коды создают два цикла.

Вот что я получаю в своей базе данных:

db

Существует цикл для списка colorId и цикл для списка quantity. Я просто хочу знать, как я могу отправить список количества и предотвратить повторение списка colorId дважды при добавлении списка количества.

Так что мне нужно руководство о том, как решить эту проблему.

Вы перебираете три цвета, затем для каждого цвета добавляете все три количества. Предполагая, что два списка согласованы друг с другом, использование одного for цикла решит вашу задачу:

public void AddColorToProductByAdmin(int productId, List<int>? SelectedColor, List<int>? ColorQuantities)
{
    if (SelectedColor is null)
        return; // нет цветов

    for (int i = 0; i < SelectedColor.Count; i++)
    {
        _context.ProductColors.Add(new ProductColor()
        {
            ProductId = productId,
            ColorId = SelectedColor[i],
            Quantity = ColorQuantities?[i]
        });
    }
    _context.SaveChanges();
}

Ответ или решение

Ваша проблема заключается в том, что при сохранении связанного элемента в таблице с многими ко многим вы получаете дублирующиеся записи в базе данных. Основной причиной этого является то, что вы используете вложенные циклы для обработки выбранных цветов и количеств, что приводит к созданию множества записей для каждой комбинации цвета и количества.

В вашем текущем коде в методе AddColorToProductByAdmin происходит следующее:

  1. Вы итератором проходите по всем выбранным цветам.
  2. Для каждого цвета вы снова запускаете итерацию по списку количеств, добавляя к каждому цвету все доступные количества. Это приводит к тому, что каждый цвет получает все суммы, что и создает дублирования.

Для решения вашей проблемы, необходимо просто использовать один цикл, в котором вы будете одновременно итеративно получать ColorId и соответствующее ему Quantity, предполагая, что списки SelectedColors и ColorQuantities имеют одинаковую длину и соответствие.

Вот переработанный код, который решает вашу задачу:

public void AddColorToProductByAdmin(int productId, List<int>? SelectedColor, List<int>? ColorQuantities)
{
    // Проверка на случай, если список цветов пуст
    if (SelectedColor is null || ColorQuantities is null || SelectedColor.Count != ColorQuantities.Count)
        return; // Или обработка ошибки, если это необходимо

    // Использование одного цикла для обработки обоих списков
    for (int i = 0; i < SelectedColor.Count; i++)
    {
        _context.ProductColors.Add(new ProductColor()
        {
            ProductId = productId,
            ColorId = SelectedColor[i],
            Quantity = ColorQuantities[i] // Берем количество по индексу i
        });
    }

    // Сохранение изменений в базе данных
    _context.SaveChanges();
}

Объяснение изменений:

  1. Проверка аргументов: Мы добавили проверку длины списков, чтобы избежать потенциальных ошибок, если они будут разной длины.
  2. Упрощение цикла: С помощью одного цикла мы объединяем информацию о цветах и количествах, что предотвращает дублирование и позволяет точно сопоставить каждый цвет с соответствующим количеством.

Важные моменты:

  • Убедитесь, что на уровне пользовательского интерфейса ваши списки точно соответствуют друг другу: каждая галочка на цвете должна иметь соответствующее количество.
  • Дополнительно, при добавлении новых свойств в модель (в данном случае Quantity), важно внимательно следить за миграциями базы данных и их корректным выполнением.

Таким образом, приведенный код решает вашу проблему. Теперь при добавлении каждого цвета в таблицу ProductColor будет добавляться соответствующее количество, избегая дублирования. Если у вас остались вопросы, не стесняйтесь спрашивать!

Оцените материал
Добавить комментарий

Капча загружается...