Рассматривая два варианта управления транзакциями, которые у вас есть, у них действительно есть проблемы.
В примере 1 транзакция не обязательно удаляется, и вы также связываете время жизни транзакции с временем жизни репозитория. Это не обязательно плохо, но если вы не используете контейнер IoC или какой-либо другой метод, чтобы гарантировать, что хранилище будет воссоздано для каждой операции базы данных, вы сможете выполнить коммит только один раз, и последующие коммиты, вероятно, потерпят неудачу.
Пример 2, к сожалению, не будет работать вообще - в Commit / RollBack вы каждый раз начинаете новую транзакцию. Особенно в случае RollBack, если он вызывался из внешнего кода в контексте транзакции, все, что вам нужно сделать, - это запустить новую вложенную транзакцию, а затем немедленно откатить ее. К сожалению, не очень полезно.
Мое личное решение вашего первого вопроса - отвести управление транзакциями от хранилища, используя окружающие транзакции в System.Transactions. Таким образом, у вас все еще есть разделение, так как окружающие транзакции не зависят от провайдера, но также у вас есть больший контроль над тем, какие из многих операций с репозиторием, которые вы можете выполнять, будут задействованы в транзакции, а не всегда будете использовать модель с одной транзакцией на операцию. , См. http://msdn.microsoft.com/en-us/magazine/cc163527.aspx для получения дополнительной информации.
Что касается вашего второго вопроса, я очень рекомендую заглянуть в контейнер IoC, такой как Castle Windsor или Unity. Вспомогательный класс, который у вас есть, гораздо лучше, чем перестройка фабрики сессий и тому подобное каждый раз, но с помощью контейнера IoC вы можете очень легко убедиться, что время жизни вашего объекта сеанса именно то, что вы хотите. Например, в ряде служб WCF Per-Call, над которыми я работаю, я использую Castle Windsor, чтобы гарантировать, что сеанс создается (и внедряется в хранилище), когда начинается операция WCF, и удаляется (вместе с хранилищем). ) когда это заканчивается.