C # - Использование транзакций на бизнес-уровне (SQLServer 2005+, Oracle) - хорошие примеры - PullRequest
6 голосов
/ 10 июня 2011

Я собираюсь создать сервис с использованием 3-уровневой архитектуры, и я действительно беспокоюсь о том, как обрабатывать операции транзакционным способом.

Я знаю, что у меня есть 2 варианта: IDbTransaction и TransactionScope ... но я не совсем решил, какой из них выбрать, хотя я провел много исследований.

Я бы выбрал TransactionScope, но не хочу использовать DTC ... плюс мне нужна поддержка SQLServer2005 и Oracle. (Я знаю, что мне нужно открыть только одно соединение за раз)

Я хотел бы видеть хорошие примеры / шаблоны их использования для обоих случаев ... Хорошие ссылки вполне подойдут.

Что-то вроде того, как будут выглядеть класс BL и класс DAL ... но также и то, как транзакции / соединения создаются и переносятся между ними.

Edit1: Я ищу способ реализации этого (но для обоих вариантов):

using(var scope = new TransactionScope())
{
    // transactional methods
    datalayer.InsertFoo();
    datalayer.InsertBar();
    scope.Complete();
}

Edit2: Поскольку Денис предложил мне очень хорошую альтернативу ... Я все еще жду, когда кто-нибудь покажет мне хороший пример модели с взаимодействием между бизнес-уровнем и уровнем данных, используя 'TransactionScope'

Спасибо.

Ответы [ 4 ]

11 голосов
/ 13 июня 2011

В настоящее время я использую несколько репозиториев и несколько подходов UnitOfWork. Допустим, у вас есть CustomerRepository и InvoiceRepository. Если вам нужно сделать это:

customerRepository.Add(customer);
invoiceRepository.Add(bill);

и эти два в качестве транзакции, то, что я делаю, это при создании хранилища, я даю им тот же UnitOfWork, как:

IUnitOfWork uow = UnitOfWork.Start();
ICustomerRepository customerRepository = new CustomerRepository(uow);
IInvoiceRepository invoiceRepository = new InvoiceRepository(uow);

так что приведенные выше утверждения теперь:

customerRepository.Add(customer);
invoiceRepository.Add(bill);
uow.Commit();

Вся магия ниже, зависит от того, что вы используете в качестве технологии данных (или ORM, например, NHibernate, или, возможно, необработанный ADO.NET - и это не рекомендуется в большинстве случаев).

Для хорошего примера по шаблону репозитория и UnitOfWorks, пройдите это руководство , но обратите внимание, что в нем не может быть несколько активных UnitOfWorks (и на самом деле лишь немногие приложения нуждаются в этом, поэтому никаких реальных проблем нет ). Кроме того, в учебном пособии используется NHibernate, поэтому, если вы не знакомы с концепцией ORM, я предлагаю вам в нее войти (если ваше расписание это позволяет).

еще одна вещь: у вас также есть более продвинутые шаблоны, такие как сеанс на разговор и т. Д., Но это продвинутый материал, в который я сейчас завершаюсь, если вы хотите взглянуть на проекты uNhAddIns ( для NHibernate также)

4 голосов
/ 13 июня 2011

Я бы выбрал TransactionScope, потому что его гораздо проще использовать, так как вам не нужно переносить объект транзакции или передавать его каждому методу. Это окружающий . Это означает, что в большинстве случаев разработчики могут почти забыть о транзакциях, написать классные бизнес-ориентированные методы, а затем добавить обертки транзакций (используя «использование») там, где это действительно необходимо, впоследствии. (звучит идиллически, я знаю, но это почти так).

Вопреки распространенному мнению, использование TransactionScope не означает, что MSDTC будет задействован, см. Здесь краткий обзор этого:

Избегать нежелательной эскалации распределенных транзакций

И, если вам действительно нужна распределенная транзакция, ну как вы планируете делать это без MSDTC? Что снова интересно с TransactionScope, так это то, что при необходимости он переходит в MSDTC, не меняя ничего в вашем коде.

3 голосов
/ 11 июня 2011

Вы можете абстрагироваться от этих двух технологий, внедрив тонкую оболочку, которую вы используете на бизнес-уровне.Допустим, что-то вроде:

using (IUnitOfWork unitOfWork = UnitOfWork.Start())
{
    // do something
    unitOfWork.Commit();
}

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

2 голосов
/ 15 июня 2011

Шаблон UnitOfWork идеально подходит для четкой обработки транзакций (между прочим). Вот хорошая реализация шаблона, используемого в некоторых тяжелых приложениях:

https://github.com/NikGovorov/Taijutsu/tree/master/Sources/Sources/Taijutsu-Infrastructure

Хотя вам придется реализовать DataProvider для ORM по вашему выбору (NH, EF, ...), но это довольно тривиально.

...