Игнорировать повторяющиеся записи и фиксировать успешные записи в 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, но оно не затронет ваши данные.

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