Абстрактные транзакции с сервисом / хранилищем / модулем работы - PullRequest
0 голосов
/ 27 июня 2011

У меня тонна транзакционного кода доступа к БД, смешанного с бизнес-логикой в ​​устаревшем коде.Я хочу разделить его на сервисы и репозитории, с контролем транзакций за пределами сервисов и абстрагированием удаленных транзакций для тестируемости.

Проблема в том, что мне нужно иметь параметр IDbConnection, включенный в транзакцию, для каждой сигнатуры метода как в сервисеи слои репозитория, и это то, что мне определенно не нравится:

void Process(Stuff s, IDbConnection connection);

Я хочу найти способ получить что-то подобное в методе верхнего уровня:

void Process(Stuff stuff, User u)
{
 using(var UoW = ???) // Start transaction
 {
  // various operations in the same transaction
  if( AuthorizationService.AuthorizesUserForStuff(u,stuff) )
  {
   StuffService.Process(stuff);
   AuditService.Success(u, stuff);
  }
  else
   AuditService.Failure(u,stuff);
  UoW.Commit();
 }
}

Репозиторий:

void Process(Stuff s)
{
 IDbCommand command = ??? //aware of current UnitOfWork
 ...
 command.ExecuteNonQuery();
}

Устаревший код не использует какой-либо ORM, он содержит множество хранимых процедур и настраиваемый SQL-код, а некоторые операции требуют обращения к базе данных, поэтому я не могу просто зарегистрироватьобъекты с unitofwork и выполняют операции в методе commit.

Пожалуйста, предложите, какой шаблон можно использовать в этой ситуации для некоторого постоянного невежества и позволит контролировать транзакции на верхнем уровне.

Ответы [ 2 ]

1 голос
/ 11 октября 2011

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

Я был бы очень заинтересован в любом другом методе.

0 голосов
/ 18 августа 2011

Мы используем OR-mapping для этого, поэтому наше решение для этого выглядит иначе. Но одним из способов сделать то же самое может быть использование абстрагированного контекста персистентности, который имеет дело с конкретными вещами базы данных, внедрение этого во все классы обслуживания, которые его используют, и создание вашей единицы работы из этого контекста на уровне «процесса», а затем разрешить экземпляру UoW управлять состоянием транзакции и соединениями, взаимодействуя с экземпляром контекста.

Что-то вроде

        using (var unitOfWork = Context.CreateUnitOfWork())
        {
            // access injected services and repositories to modify stuff

            unitOfWork.Complete();
        }

Когда вы на самом деле выполняете DB-вещи, в вашей ситуации вы бы запрашивали соединение с DB из вашего (внедренного) экземпляра контекста, что-то вроде этого

        using (var conn = Context.AquireDbConnection())
        using (var command = conn.CreateDbCommand())
        {
            // do db stuff

            command.ExecuteNonQuery();
        }

ваша конкретная единица работы / реализации контекста должна быть здесь достаточно умна, чтобы распознать, должно ли возвращаемое соединение быть новым или окружающим соединением, основываясь на том, есть ли там активная окружающая бизнес-транзакция или нет.

Очевидно, что для этого механизма вам потребуется изоляция для каждого запроса, а время жизни экземпляра контекста будет зависеть от запроса.

...