почему структура сущностей сохраняет только последний элемент списка? - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть 2 объекта с отношением один ко многим.Я пытаюсь добавить несколько ProductImages с одним и тем же ProductId в базу данных, используя общий репозиторий.

Я попытался сохранить список ProductImage в репозиторий с помощью dbSet.AddRange.после этого я сохранил его с context.SaveChanges ();я также попытался зациклить список ProductImage и добавить каждый элемент с помощью dbSet.Add .and than context.SaveChanges ().

методы репозитория:

    public virtual void Add(TEntity entity)
        {
            dbSet.Add(entity);
        }

        public virtual void AddRange(List<TEntity> entityList)
        {
            dbSet.AddRange(entityList);
        }
        public void Save()
        {
            context.SaveChanges();
    }

результат - объектсохраненный в базе данных всегда последний - но я хочу сохранить их все.

Редактировать метод добавления объектов:

        private  Task<int> InsertProductImagesToDB(List<ProductImageVM> productImages, int productId, List<IFormFile> imageFiles)
        {
            if (productImages?.Any()==true)
            {
                List<ProductImage> dbEntitys = new List<ProductImage>();
                for(int i=0; i< productImages.Count; i++)
                {
                    ProductImage p = productImages[i].ConvertToProductImageEntity(imageFiles[i], productId);
                    dbEntitys.Add(p);
                }
                ImagesRepository.AddRange(dbEntitys);
                ImagesRepository.Save();
                return Task.FromResult(dbEntitys.First().Id);//return first productImage as the main image
            }
            return Task.FromResult(-1);
        }

какнекоторые из вас упоминали в комментариях - конструктор объекта не находится вне цикла.во время отладки я вижу, что список dbEntitys содержит 2 элемента с различными значениями.

изображение dbset после добавления объектов перед сохранением изменений: enter image description here таблица дБ после сохранения изменений: enter image description here

Ответы [ 2 ]

1 голос
/ 27 сентября 2019

Чтобы расширить комментарий Стива, проблема, скорее всего, не в EF или добавлении элементов в DbSet, а в том, как вы заполняете список сущностей для сохранения.

Возьмем, к примеру,

List<ProductImage> productImages = new List<ProductImage>();
Product product = context.Products.Single(x => x.ProductId == productId);
ProductImage productImage = new ProductImage();
for (int count = 1; count < 5; count++)
{
   productImage.ImageNumber = count;
   productImage.Product = product;
   productImages.Add(productImage);
}

// ...
context.ProductImages.AddRange(productImages);

Проблема с приведенным выше кодом заключается в том, что цикл просто обновляет одну и ту же единственную ссылку объекта ProductImage.Список будет содержать 5 ссылок на одно и то же изображение, и номер этого изображения будет «5».

Вместо этого:

List<ProductImage> productImages = new List<ProductImage>();
Product product = context.Products.Single(x => x.ProductId == productId);
for (int count = 1; count < 5; count++)
{
   ProductImage productImage = new ProductImage();
   productImage.ImageNumber = count;
   productImage.Product = product;
   productImages.Add(productImage);
}

// ...
context.ProductImages.AddRange(productImages);

Перемещая конструктор для ProductImage в цикл, каждое изображение является отдельной ссылкой, в результате чего в коллекции 5 уникальных элементов.

Важной деталью является то, что если все изображения относятся к одному и тому же продукту, вы делаете используете одну ссылку на продукт для всех изображений.Загружен ли этот продукт из базы данных (см. Выше) или создан как новый элемент.Типичные ошибки, с которыми сталкиваются разработчики, плохо знакомые с EF:

List<ProductImage> productImages = new List<ProductImage>();
for (int count = 1; count < 5; count++)
{
   Product product = new Product { ProductId = productId };
   ProductImage productImage = new ProductImage();
   productImage.ImageNumber = count;
   productImage.Product = product;
   productImages.Add(productImage);
}

// ...
context.ProductImages.AddRange(productImages);

Где у них может быть существующий идентификатор продукта, выбранный пользователем, и они не хотят обращаться к базе данных, чтобы загрузить его, поэтому онипросто создайте сущность Product и установите ID, думая, что все будет хорошо.Проблема здесь заключается в том, что каждый экземпляр Product будет отдельным экземпляром, и когда вы добавите ProductImage в DbSet, все неотслеживаемые объекты, связанные с этим образом продукта (в данном случае Product), будут также обрабатываться как «Добавления».В результате 5 новых идентичных Продуктов (с новыми идентификаторами) будут добавлены в базу данных при условии, что Идентификатор продукта PK был настроен как Идентичность, или вы получите ошибку при вставке дублирующих идентификаторов.С EF важно работать с уникальными экземплярами, где вы хотите создать уникальные записи, и работать с одним экземпляром (загруженным из БД, созданным новым или созданным как заглушка и присоединенным к контексту), где вы хотите сослаться на один экземпляр.существующая или новая строка.

0 голосов
/ 29 сентября 2019

после того, как несколько дней ударился головой о стену - я, наконец, нашел решение.

проблема была в моем объекте ProductImage, который выглядел так:

   public class ProductImage : ImageProp, DBEntity
    {
        [Column("Name", TypeName = "nvarchar(200)"), Required, Display(Name = "שם"), MaxLength(200)]
        public string Name { get; set; }

        public Product Product { get; set; } 

        [Required]
        public int ProductId { get; set; }

    }

, поэтомупроблема заключалась в следующей строке:

  public Product Product { get; set; } 

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

удаление этой строки решило проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...