Игнорировать повторяющиеся записи и фиксировать успешные записи в DbContext.SaveChanges() в EF Core
У меня есть ASP .Net Core 2.2 Web API. В одном из моих действий контроллера я добавляю несколько строк в таблицу базы данных MySQL (я использую Pomelo).
Так, например:
_dbContext.AddRange(entities);
_dbContext.SaveChanges();
У сущностей, которые я добавляю, есть два первичных ключа (составной первичный ключ), и ключи уже заполняются в коллекции сущностей, когда я добавляю их в DbContext (т. Е. Я сам устанавливаю ключи - здесь нет "автоматического увеличения" или чего-то подобного то где база данных генерирует ключи)
Если какая-либо сущность, которую я добавляю, уже существует в базе данных с точки зрения дублирования первичного ключа, то, очевидно, SaveChanges() генерирует исключение, и вся транзакция откатывается.
Есть ли способ сказать EF Core игнорировать объекты, которые потерпели неудачу? т.е. игнорировать сущности, которые уже существовали в базе данных, и фиксировать сущности, которые успешно (то есть, которые не существовали в базе данных)? Вместо текущего поведения, которое вызывает исключение и откатывает всю транзакцию?
Спасибо
1 ответ
Похоже, у вас есть проблемы с бизнесом на месте. Во-первых, вам нужно решить, что произойдет, если у вас уже есть объект с таким же идентификатором, и кто-то пытается вставить новый объект (новую информацию) с тем же идентификатором.
Похоже, вы уже решили: вы хотите отказаться от действия.
Это как-то необычно, потому что если вы получаете новые данные от клиентов этого API о сущности, которая уже существовала в вашей базе данных -> это больше похоже на обновление.
Существуют некоторые библиотеки, которые могут делать что-то подобное: https://github.com/borisdj/EFCore.BulkExtensions (которая в настоящее время работает только с MsSQL)
Используя эту библиотеку (которая известна и уже упоминалась Microsoft как EF Core Tool: https://docs.microsoft.com/en-us/ef/core/extensions/), у вас есть возможность:
Вставьте или обновите все данные (все столбцы), если вы найдете объект с таким же идентификатором (Upsert):
context.BulkInsertOrUpdateAsync(entitiesList);
Синхронизируйте сущности из вашей базы данных с любыми сущностями, которые вы получаете от клиентов:
context.BulkInsertOrUpdateOrDeleteAsync(entitiesList);
Скорее всего, вы не найдете что-то уже реализованное для вашего случая, но вы можете настроить эту библиотеку:
BulkInsertOrDropAsync
Который будет делать что-то вроде:
WHEN MATCHED THEN UPDATE SET A.ID=A.ID --The ID's are already the same so nothing will happen
WHEN NOT MATCHED THEN INSERT(A.ID,A.NAME,A.CODE,A.DESCRIPTION)
Что на самом деле не DROP, но оно не затронет ваши данные.