TransactionScope на бизнес-уровне для грязного асинхронного чтения

Я разрабатываю службу веб-API .NET Core и использую следующий метод в BL:

public async Task<SetParams> GetParams(CreateRequest request)
        {
            var user = await _userRepository.GetUserByLogin(request.Login);  
            var client = await _clientRepository.GetClientByCode( request.ClientCode);

            // many other getters here 

            return new SetParams
            {
                IdUser = user.IdUser,
                ClientName = client.Name,
                // and so forth...
            };
        }

У меня есть требование, чтобы все объекты находились в режиме «грязного чтения».

Итак, я пытался использовать TransactionScope следующим образом:

public async Task<SetParams> GetParams(CreateRequest request)
        {
            using (var ts = new TransactionScope(
                TransactionScopeOption.Required,
                new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
            {
                var user = await _userRepository.GetUserByLogin(request.Login);
                var client = await _clientRepository.GetClientByCode(request.ClientCode);

                // many other getters here 

                ts.Complete();

                return new SetParams
                {
                    IdUser = user.IdUser,
                    ClientName = client.Name,
                    // and so forth...
                };
            }
        }

Но: 1) это прочитало зафиксированный режим (я знаю из это сообщение о том, что я должен начать транзакцию, но у меня здесь нет сеанса или контекста базы данных, потому что я нахожусь в BL, а не в DAL)

и 2) получение исключения TransactionScope должен быть размещен в том же потоке, в котором он был создан.


person Dmitry Stepanov    schedule 03.09.2018    source источник
comment
Не рекомендуется делать множество запросов к репозиторию, если вы используете только несколько полей из каждого. Реализуйте функцию DL, которая извлекает только те поля, которые вам нужны в BL.   -  person Neil    schedule 03.09.2018
comment
В .NET 4.5.1 добавлена ​​возможность передавать конструктору TransactionScopeAsyncFlowOption, который должен адресовать 2.   -  person Damien_The_Unbeliever    schedule 03.09.2018
comment
particular.net/blog/   -  person Mrinal Kamboj    schedule 03.09.2018


Ответы (1)


Вам нужна транзакция для набора запросов на чтение (грязное чтение)

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

С чего начать транзакцию, BL/DAL, нужен ли ей DbContext?

Это зависит от вашего варианта использования, если ваш дизайн таков, что несколько бизнес-запросов, которые должны быть частью транзакции, отправляются из BL, тогда это допустимая отправная точка, особенно с использованием транзакции Ambient (TransactionScope). Явное Session или Context для инициирования транзакции является одним из механизмов, поскольку все общие запросы легко включаются в один и тот же контекст транзакции, но подобное возможно при использовании TransactionScope или CommittableTransaction, вы можете использовать TransactionScopeOption для обеспечения участия различных запросов:

  1. Использование Requires New для инициирования внешней транзакции на уровне BL и DAL с использованием Required для обеспечения того, чтобы для зачисления использовался один и тот же контекст транзакции. Соединение с базой данных должно автоматически зачисляться в доступную область.
  2. Используя CommittableTransaction, тот же объект, созданный в BL, передается в репозитории DAL, и там явно зачисляются объекты Connection.
  3. Если ваше требование немного более конкретное, когда No Commit возможен до тех пор, пока не будут завершены все дочерние операции в отдельных потоках, просмотрите DependantTransaction, который также является частью System.Transaction, но выполняет гораздо более жесткую привязку, в основном для многопоточных сценария, вам может не понадобиться это для вызовов Async Await, так как вы завершите только тогда, когда все awaits будут завершены.

Проблема, связанная с TransactionScope, должна быть удалена в том же потоке, в котором она была создана.

Решение находится здесь, это было введено в .Net4.5.1 и обеспечивает использование TransactionScope в асинхронных вызовах.

Уровень изоляции сервера Sql для запросов

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

person Mrinal Kamboj    schedule 03.09.2018