Добрый день. В разработке приложение для управления продажами.
На текущий момент имею следующую архитектуру:
DomainModel - объекты для получения данных из БД (Чеки, Операции, Товары, Склады)
DAL - шлюзы к БД (IChequeGateway, IOperationGateway, ISellerGateway и подобное для получения данных). Эти шлюзы используют IDatabaseGateway - обертка над Firebird.
BLL - команды (CreateCheque, GetAllCheque, GetAllSellers, GetAllCustoms и подобное)
Вопрос следующий: необходимо выполнить команду CreateCheque в рамках одной транзакции БД - создать чек, добавить его товары, добавить в операции списание товаров, запись в лог.
Очевидно, при этом можно либо обратиться к разным шлюзам - но тогда необходима зависимость от транзакции БД (что нарушает абстрагирование шлюза от конкретного источника данных)
Либо провести все обращения к разным таблицам в классе, реализующем IChequeGateway - но тогда мы работает не только с таблицей чеков.
Обращение к БД происходит внутри шлюзов через IDatabaseGateway (класс-обертка над FirebirdClient).
Возможно, немного сумбурно описал, но пока как умею.
Подскажите пожалуйста более-менее корректный выход из сложившейся ситуации. Такую многослойную архитектуру с БД реализую впервые (C#)
Еще видится вариант скрыть транзакцию БД IDbTranscation за своей ITransaction. Только тогда вопрос - как красиво в конкретном шлюзе вытащить из нее транзакцию БД?
Олег, тут не нужно бегать за красотой. Тот вопрос, который Вы описали, можно было бы решить просто хранимой процедурой, вызываемой в рамках обычной транзакции. Куча слоёв в данном случае - академический подход, но так ли он нужен?
Максим Кузнецов: спасибо за ответ. TransactionScope смотрел, но решил проблему несколько иначе:
UI вызывает CommandInvoker, который содержит все шлюзы к таблицам + обертку над драйвером firebird. Транзакция стартует внутри метода инвокера на уровне драйвера, и все необходимые методы шлюзов таблиц работают в рамках этой транзакции.
Пример и правда слегка учебный - накрутил слоев, чтобы получше разобраться в PoEAA.