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

Друзья:
//devdigest platform - новости и полезные статьи о дотнете.

Про производительность Entity Framework

August 15, 2019

Во-первых существует whitepaper по производительности EF, из которого можно узнать очень много грязных низкоуровневых подробностей работы EF, но он не обновлялся для EF Core, поэтому в чём-то не актуален. Хотя концептуально всё-равно полезен, если у вас возникнет необходимость супер-оптимизировать и скорость работы EF Core тоже:

Performance considerations for EF 4, 5, and 6

Но whitepaper никак не решает проблему того, что Entity Framework в принципе не приспособлен для массовых операций изменения данных - массовых Insert, Update и Delete. Тут проблема лежит в двух плоскостях - тормозит DbContext и тормозит сама база данных, так как EF производит все изменения отдельными sql запросами (хотя и в рамках одного физического запроса к базе данных).

Техники работы с контекстом, чтобы он меньше тормозил при Insert рассмотрены в этой статье Rick Strahl: Entity Framework and slow bulk INSERTs

И техника с пересозданием DbContext и “пакетным” сохранением описанная там, довольно эффективна, а в этом ответе на SO есть сравнение влияния размера пакетов на скорость сохранения, так чтобы вы могли выбрать оптимальный.

Для ускорения контекста при массовом обновлении и удалении, тоже есть “хаки”:

  1. Аттачить к контексту “болванки” (сущности, которые на загружались из БД и которых нет в контексте), а затем явно их помечать в контексте как обновлённые или удалённые (через DbContext.Entry), кое-что по этой теме можно найти здесь.
  2. Также как при Insert пакетировать сохранение.
  3. Также как при Insert отключать автоматический поиск изменений в контексте.

Но самый эффективный путь - это вообще отказаться от использования Entity Framework для массовых операций изменения данных и, например, напрямую использовать SQL. (Если решите пойти этим путём, то загляните ещё в эту статью, в ней автор рассказывают свою идею как сделать такие SQL-запросы более типизированными.)

А для тех случаев, когда даже SQL тормозит, можно пойти дальше и использовать более производительные способы, которые предоставляет база данных.

Например, вот в этой статье, рассказано, как использовать специальные возможности MSSQL Server для ускорения Insert и Update на уровне базы данных: Entity Framework: повышаем производительность при сохранении данных в БД. Подобную возможность, кстати, предоставляет и PostgreSQL.

Ну и буквально на днях наткнулся на библиотеку Linq2Db у которой есть интеграция с Entity Framework и с помощью которой, судя по всему, без проблем можно будет делать массовый Insert, Update, Delete. Кстати, умеет использовать специальные высокопроизводительные операции специфичные для базы данных. Но предупреждаю, сам её ещё не использовал.