В нашем приложении у нас был похожий сценарий, избегайте максимально возможной блокировки при выполнении массивного выбора, а затем создавайте много вставок после некоторой операции с памятью.
- Если вы хотите прочитать все заранее
Решение A ) Используйте область транзакции, которая включает чтение и обновление
PRO: данные безопасно обновлены
Минусы: блокировки вызваны чтением (повторяющиеся чтения) и обновлением
Решение B ) Не используйте транзакцию и обновляйте все данные вместе
PRO: данные безопасно обновлены, но данные, которые вы прочитали, могли быть изменены
CONS: блокировки, вызванные обновлением на весь период (EF создает по умолчанию транзакцию)
Решение C ) Обновлять пакетами вместо всех данных все вместе (можно использовать, только если выбор не блокирует таблицы, в противном случае вы получаете то же поведение, что и B
PRO: короткие и меньшие блокировки в обновленных таблицах
Минусы: Вы увеличиваете изменение подверженности устареванию данных
- Если вы хотите (и можете) читать партиями
Решение D ) Разбивка проблемы и разбиение операций чтения могут помочь вам уменьшить блокировку, чтобы вы могли использовать область транзакции для переноса как чтения, так и записи (как решение A)
PRO: данные безопасно обновлены
Минусы: блокировки, вызванные чтением (повторяющиеся чтения) и обновлением, воздействия варьируются в зависимости от размера пакета и характера самого запроса
Решение E ) Не используйте транзакции, поэтому только обновление вызовет небольшие блокировки (как в решении B)
PRO: данные безопасно обновлены, но данные, которые вы прочитали, могли быть изменены
Минусы: блокировки вызваны обновлениями
Как правильно заметил @Ladislav, множественные вставки действительно неэффективны, и быстрое профилирование базы данных показывает, как в этом случае происходит сбой волшебства ORM.
Если вы хотите использовать EF для выполнения пакетных операций, таких как вставки, обновления и удаления, я рекомендую вам взглянуть на это:
EF Utilities
Я склонен проверять блокировки с помощью этого запроса, надеюсь, поможет лучше понять, что происходит.
SELECT
OBJECT_NAME(p.OBJECT_ID) AS TableName,
resource_type,
resource_description
FROM
sys.dm_tran_locks l JOIN
sys.partitions p ON
l.resource_associated_entity_id = p.hobt_id