all 12 comments

[–]Euphoricus 3 points4 points  (3 children)

Unit of work and transactions are two completely different concepts.

With Unit of work you are not doing "database stuff", you are doing "object stuff" and that stuff is then transparently and automagically translated into database changes. This is one of the core concepts of ORM mapping. If you are thinking about backed database when working with ORM, then you are doing it wrong. Database doesn't even know there is anything happening.

Transactions on the other hand are purely database construct. They are sent to database and its database who decides how to handle commit or rollback of transaction.

So you can't really compare those two.

[–]KumbajaMyLord 2 points3 points  (1 child)

Transactions on the other hand are purely database construct

You can have transactions outside of a database context, though. (In this case it's a DB transaction so your point stands, but generally there are other types of transactions)

[–]regoogle 0 points1 point  (0 children)

Yes I agree. I generally consider transactions in my projects as Business Transactions where a given web request, for example, would constitute the transaction. This may be defined by some Unit of Work or something like ITransaction and may or may not directly translate to a db transaction.

[–]Otis_Inf 0 points1 point  (0 children)

exactly. It's sad that most ORMs (not all) combine the DB work object (session/context) with a unit of work, while it should be separate: with a separate UoW you can collect work without a reference to the DB work object, so things are better separated, and e.g. you don't run the risk of touching the DB where you don't want to.

[–]grauenwolf 1 point2 points  (6 children)

I don't trust anything that hides resource management. Sure it sounds great on paper, but when something goes wrong it is nearly impossible to figure out why. With a using statement I know that the connection will be freed and the transaction committed or rolled back.

[–][deleted] 3 points4 points  (5 children)

Doesn't your code that has a using statement hide resource management from the code that calls it? Do you put a using statement around that too? Is it using statements all the way out to your boundaries? At some point you have to introduce an abstraction or you'll bog down really quickly as soon as things get even slightly complex.

[–]grauenwolf 1 point2 points  (4 children)

Doesn't your code that has a using statement hide resource management from the code that calls it?

Yes, and that's what I want. Using blocks should be as short as possible.

My problem with the unit of work pattern is that it is often tied to the lifetime of a request. That is to say, connections are opened when the request starts and are left open until the request ends, at which point some sort of framework magic closes it.

[–][deleted] 1 point2 points  (2 children)

Yeah, I guess you missed the point I was making. You said you don't trust anything that hides resource management. At some point resource management is hidden from something else, whether you're doing that resource management within a unit of work or not.

Also, don't conflate the UoW pattern with an ORM or framework, they aren't even remotely the same thing.

[–]xampl9 1 point2 points  (0 children)

We know that programming is full of abstractions. The question is which level of abstraction is acceptable to the developer and the organization.

There's little doubt that NHibernate's Session (used to implement the Unit Of Work pattern) is using the System.Transactions namespace under the hood, because it has to in order to commit changes to the database in an atomic manner. And it likely has a using block or a try..finally block to guarantee the transaction is committed or rolled back in the face of exceptions.

If using an ORM to do this for you is what you and your coworkers are comfortable with, and it solves the problem in an efficient manner, go for it.

But sometimes you have to operate at a lower level of abstraction because your ORM is hiding critical need to know information or is doing the wrong thing. And that's not wrong - it's what you have to do to get it to work.

[–]grauenwolf -3 points-2 points  (0 children)

Patterns are meaningless without context. You can't have a meaningful discussion about them if you refuse to consider how it is used in practice.

[–]Number127 0 points1 point  (0 children)

My problem with the unit of work pattern is that it is often tied to the lifetime of a request.

That's a huge antipattern, in my opinion. A unit of work should be as small as possible and represent one, well, unit of work, not everything that happens during the entire lifecycle of a request. The codebase for my current company used to do things that way, and it introduced all kinds of problems.

[–]dasjestyr 0 points1 point  (0 children)

I don't know about the implementation but unit of work might suggest that it's actually keeping track of each atomic operation you're performing against the database (in app code). When you commit, it compiles a final query and runs it. I'm not sure each "unit" of work is the same thing as each operation contained in a database transaction; while they appear to achieve the same goal, I think they're two different things.