C# - Usage of transactions in business layer (SQLServer 2005+ , Oracle) - good examples

て烟熏妆下的殇ゞ 提交于 2019-12-03 14:10:14

What I use in this case currently is multiple repositories and multiple UnitOfWork approach. Lets say that you have CustomerRepository and InvoiceRepository. If you need to do this:

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

and have these two as a transaction, then what I do is on repository creation I give them the same UnitOfWork, like:

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

so that statements above are now:

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

All magic is beneath, dependent on what you use as data technology (either ORM like NHibernate, or maybe raw ADO.NET - and this is not recommended in most cases).

For a good example on repository pattern and UnitOfWorks, go through this tutorial, but note that in it you can't have multiple UnitOfWorks active (and few applications need that actually, so no real problem there). Also, the tutorial uses NHibernate, so if you are not familiar with ORM concept, I suggest you get into it (if your timetable allows it).

one more thing: you also have more advanced patterns here, like session per conversation and such, but this is advanced stuff in which I'm having my head wrapped in right now, if you want take a look at uNhAddIns projects (for NHibernate also)

I would go for TransactionScope, because it's much simpler to use, as you don't need to carry over a transaction object, or pass it to every method. It's ambient. It means, most of the time, developers can almost forget about transactions, write cool business-oriented methods, and then, later, add transaction wrappers (using 'using') where it's really needed, afterwards. (sounds idyllic I know, but it's almost that).

Contrary to popular belief, using a TransactionScope does not means MSDTC will be involved, see here for a recap on this:

Avoid unwanted Escalation to Distributed Transactions

And, if you really need to have a distributed transaction, well, how do you plan to do it without MSDTC anyway? What's interesting with TransactionScope again, is it will escalate to MSDTC if needed, without changing nothing in your code.

You can abstract these two technologies by implementing a thin wrapper, which you use in your business layer. Lets say something like:

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

You can then use an implementation that just opens a database transaction. If you need to involve another transactional system, you just switch the unit of work implementation to one which opens a TransactionScope rather than the simple database transaction.

UnitOfWork pattern is perfect for clear transaction handling (among other things). Here's a good implementation of the pattern used in some heavy duty applications:

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

Although you'd have to implement DataProvider for ORM of your choice (NH, EF,...) but it's fairly trivial.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!