Похоже, вы не закрываете транзакцию, если user
равно нулю. Вот что на самом деле происходит в вашем коде:
- вы вызываете метод, который вызывает
_context.Database.BeginTransaction()
- транзакция открывается для соединения
user
имеет значение null , что приводит к тому, что не вызывается CommitAsync
или RollbackAsync
- транзакция все еще используется даже после завершения выполнения метода, она открыта в соединении
- вы вызываете этот метод снова, возможно при создании нового контекста EF, однако, контекст EF не создает новое соединение каждый раз, он будет повторно использовать существующее из пула соединений
- Контекст EF выбирает соединение, которое использовалось на шаге 2, с уже открытым транзакция
- вы пытаетесь открыть другую транзакцию в соединении, которое уже открыло транзакцию, и получаете исключение (даже если на этот раз
user
не равно null)
Я думаю, это должен работать таким образом. Вы можете попробовать совершить / откатить транзакцию, даже если в базе данных ничего не изменилось, это должно устранить проблему.
В документации SqlConnection.BeginTransaction говорится:
Вы должны явно зафиксировать или откатить транзакцию с помощью метода Commit или Rollback.
ОБНОВЛЕНИЕ Если упомянутое выше не помогло, есть другие вещи, которые следует рассмотреть и проверить:
- Существуют сторонние библиотеки которые взаимодействуют с базой данных и открытыми транзакциями. Иногда они помогают работать с EF и предоставляют такой функционал, как
BatchInsert
или BatchUpdate
. Их можно было бы вызвать где-нибудь в вашем коде. - Одновременный доступ к одному контексту EF, если он хранится, например, в поле stati c и несколько потоков пытаются использовать его одновременно.
- Внешний код может создать транзакцию до того, как ваш код был вызван, также ваш код может создать транзакцию во вложенных вызовах.
Обратите внимание на все места, где контекст EF вызывает исключение используется.