Проблемы параллелизма при использовании DbContext.Database.Connection.CreateCommand - PullRequest
1 голос
/ 01 мая 2011

Я попытаюсь объяснить это, фактически не разбирая весь дизайн приложения, над которым я работаю. Потому что, кто заботится об этом. Если это уместно, я могу дать больше подробностей, но я думаю, что я расскажу обо всем ниже.

основная проблема :

У меня есть несколько хранимых процедур, которые мне нужно периодически выполнять. Я получаю имена процедур из таблицы базы данных, поэтому мое приложение не имеет о них жестко запрограммированных знаний. Это по замыслу. В настоящее время я использую инфраструктуру сущностей для доступа ко всем данным.

Мое приложение является многопоточным - я беру все процессы, которые мне нужно запустить, затем перебираю каждый из них, беру его свойства из таблиц конфигурации и ставлю в очередь для запуска в отдельном потоке в пуле потоков приложения.

Я использую метод Database.Connection.CreateCommand и выполняю процедуры - извлекаю данные в таблицу данных. Это хорошо работает, когда я выполняю только один процесс, но когда

Проблема в том, что я сталкиваюсь с проблемами параллелизма. Я получаю конкретное исключение

System.Data.SqlClient.SqlException: Новая транзакция не разрешена, потому что в сессия.

Я предполагаю, что это потому, что я пытаюсь выполнить свою процедуру, одновременно обращаясь к свойствам другой процедуры через структуру сущностей.


Потенциальные решения / ходы мыслей, которые происходят со мной :

  • Я могу заставить это работать нормально, используя метод DbContext.Database.SqlQuery, если я напишу класс модели с полями, которые мне нужны. Но что, если я вообще не хочу писать модельный класс? Есть ли способ, которым я могу сделать это и позволить сущностной структуре фактически обработать запрос?

  • Я мог бы захватить все свойства, прежде чем начать выполнение каких-либо процедур. Это, вероятно, будет работать нормально. Если я определяю свои свойства как ICollections на модели, которая говорит мне, какую процедуру запускать, есть ли способ заставить их загружаться, когда я выбираю указанную модель из БД, а не когда я повторяю их позже, чтобы прочитать их?

1 Ответ

4 голосов
/ 01 мая 2011

Основная проблема заключается в том, что вы используете одно соединение с базой данных (Database.Connection возвращает один и тот же экземпляр для всех ваших вызовов CreateCommand) несколькими потоками, и вы пытаетесь одновременно определить несколько транзакций. Решение для этого сценария только одно - использовать новое соединение для каждой хранимой процедуры / потока. Вы должны быть в состоянии получить строку подключения, вызвав Database.Connection.ConnectionString.

  • Ваше первое решение не решит проблему, если вы не запустите новый контекст в каждом потоке.
  • Database.SqlQuery всегда требуется тип для загрузки данных. Entity Framework упрощает доступ к данным, сопоставляя наборы результатов с типами. Если у вас нет шрифта, вы не можете воспользоваться EF.
  • Способ немедленной загрузки отношения называется активной загрузкой и выполняется методом Include, используемым в запросе. Вы просто скажете, какие свойства навигации в сопоставленном объекте должны быть загружены немедленно.
...