Проблема Вставьте / обновите EF Core DbContext в функции Azure QueueTrigger (многопоточность) - PullRequest
0 голосов
/ 16 октября 2018

При использовании EF Core 2.1 DbContext в функции Azure QueueTrigger я получаю исключение нарушения PK.Вероятно, это связано с тем, что DbContext не является поточно-безопасным , а функция Azure параллельно запускает разные экземпляры.Я прочитал довольно много, но не могу найти хороший подход для решения этой проблемы.

Вот мой сценарий (шаблон производитель-потребитель):

У меня есть ЗапланированоФункция Azure , которая вызывает API для получения проектов из разных внешних систем.Чтобы получить всю необходимую информацию для проекта, мне нужно запустить другие запросы к другим внешним службам, поэтому я отделяю это от другой функции Azure, поэтому функция «Запланировано» просто помещает сообщение в очередь для каждого проекта, например « Sync Project».ID 101 ”.

Другая Функция QueueTrigger срабатывает каждый раз, когда сообщение ставится в очередь, поэтому это означает различные экземпляры, работающие параллельно .Эта функция должна собирать все данные определенного Проекта , а это означает, что нужно больше обращений к другим внешним службам / API, чтобы (каким-то образом) объединить всю информацию о Проекте .ИМХО, это хорошо сделать так, так как я могу обрабатывать несколько проектов параллельно, и я могу масштабировать функцию, если мне это нужно.

Как только у меня будет все это Project infoЯ хочу сохранить его в базе данных SQL с использованием EF Core (и здесь возникает проблема)

Данные проекта включают в себя пользователей в проекте, и каждый пользователь имеет определенный GUID в качестве PK (исходя из внешней системы).Это означает, что у меня могут быть повторные идентификаторы пользователей в разных экземплярах функций, и здесь возникает проблема, так как при попытке сохранить информацию о пользователе в таблице SQL я могу получить исключение дублирования PK, так как несколько экземпляров функций могут пытаться вставить одного и того же пользователяв то же время (когда экземпляр A проверяет, существует ли пользователь, он получает значение False, но другой экземпляр B фактически добавляет этого пользователя, поэтому, когда экземпляр A пытается выполнить вставку, происходит сбой).

Думаю, я могу заблокироватьDbContext каким-то образом, но не уверен, что это хорошо, так как у меня также есть веб-сайт, выполняющий запросы к базе данных SQL (запросы только для чтения на данный момент, но могут быть обновления и в будущем).

Другая идея может состоять в том, чтобыотправить всю информацию о проекте в другой файл очереди / большого двоичного объекта и иметь другую функцию в режиме Singleton , которая вставляет данные в SQL.

Я создал этот проект, упрощая мой сценарий, но достаточновоспроизвести проблему и понять проблему.https://github.com/luismanez/queuetrigger-efcore-multithreading

Есть еще идеи или рекомендуемые подходы?(откройте для изменения архитектуры, если найдете что-то лучшее)

Большое спасибо!

1 Ответ

0 голосов
/ 24 октября 2018

«Более легким» способом может быть выполнение некоторой поддержки в базе данных.Вот пример того, как это сделать с EF Core: https://www.flexlabs.org/2018/02/adding-upsert-support-for-entity-framework-core

...