NHibernate ISession
не является потокобезопасным, период.
Из NHibernate справочной документации Chapter 1, Getting started section:
ISession
не является поточно-объект, который представляет собой единый блок-оф-работы с базой данных.
Вместо этого вы должны изменить свой старый код.
Этот фрагмент кода в любом случае похож на ужас кодирования. Он страдает от n + 1 нагрузки плохой практики. Обычно это происходит при неправильной настройке ленивой загрузки (забыв установить адекватное значение batch-size
в сопоставлениях сущностей и коллекций, не задав параметр конфигурации default_batch_fetch_size
). Но там, это явно закодировано!
Вызов DB в цикле - это анти-шаблон производительности, который вы должны исправить первым. Вызов его в AsParallel
выглядит только как плохая попытка от первоначального разработчика «оптимизировать» этот ужас кодирования.
Чтобы исправить это, вы должны загрузить все свои данные за один раз, а затем отправить его в свой список по мере необходимости. Сначала вы можете проецировать свои данные в словарь, чтобы избежать алгоритма диспетчеризации O (n²).
После того, как сделали, AsParallel
должен был исчезнуть, и ваша проблема безопасности нитей тоже.
Если эта вещь слишком сложная (что больше похоже на то, что показывает ваш пример), или действительно соответствует чему-то, что необходимо сделать с помощью параллелизма, тогда вы должны создать экземпляр одного выделенного ISession
для каждого GetData
в вашей параллельной обработке.
Важно ли, чтобы этот кусок кода был многопоточным? Если да, то почему? Это из-за производительности (это то, что мы могли бы решить по-другому) или объем работы по ее изменению (что не так легко решить)? –
Тип приложения также имеет важное значение.Если это веб-сайт, добавление параллелизма в обработке HTTP-запросов является ужасным выбором для масштабируемости приложения и его следует избегать любой ценой. –