Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


A Pure Object-oriented Domain Model by a DB Guy, Part 5 : Page 2

This is the fifth part in a series of articles by Jimmy Nilsson on a new architecture for enterprise applications in .NET. The new architecture is purely object-oriented with maintainability as the number one goal, while still focusing on roundtrips and the data access code to get good performance. In this article, Jimmy will discuss the new architecture from a persistence access layer perspective.

What's the Problem?
So, before we get started, let’s think for a minute about the problems we are trying to solve with this layer today. First of all, the main thing that we are trying to achieve with the Persistence Access layer is to encapsulate details about the database. That is what this kind of layer is for.

Another, and less common purpose of this layer, is to completely encapsulate and hide ADO.NET for the rest of the application. Sure, ADO.NET is the best so far and it is nothing to be ashamed of, but I don’t like the so far. Microsoft has a history of switching data access APIs pretty often. When the next generation is here, we'll only have to make changes to one layer to switch to the new API if ADO.NET-related code has been carefully encapsulated there.

We don’t have to change to a new API as soon as it arrives, of course. I still have several applications running with clients that use DAO and RDO. Those applications aren’t changed very often at all, but needless to say they still work.

One of the most important things we can do to improve scalability is decrease the times for holding onto locks. Therefore I want the Persistence Access layer to start work on the database as late as possible, yet finish as soon as possible. As you will see, I’m trying hard to gather all the information needed for the work of the Data Tier. In this way when the Persistence Access layer starts its work against the database, nothing gets in between.

Likewise, I try to reduce roundtrips between the Persistence Access layer and the database, which is actually one reason why I prefer to call stored procedures from the Persistence Access layer. As a result I've got a good opportunity to reduce a couple of roundtrips. I could even go as far as to bunch together several stored procedure calls into one single SQL batch (which I did in my book [7]), but what I also have now is an alternate implementation that makes one roundtrip for each stored procedure call. It’s not all that obvious in .NET that using the SQL batch solution is preferable in every situation.

Please note that there is nothing in the solutions I’m discussing today that requires the usage of stored procedures. You can like all the rest of it and use the architecture even if you prefer dynamic SQL. Some of the work that I put in the stored procedures will of course have to move to the Persistence Access layer, but that’s it.

When talking about this layer in other architectures, it’s not unusual to find it called Data Access layer, which is a relatively small difference of course. A much more important difference is that in my architecture, the Persistence Access layer knows about the Domain Model layer and not the other way round, which is what usually happens. This means that the domain model itself has no idea at all about persistence. We will discuss this more later.

Main Parts of Solution
The layer we are about to discuss consists mainly of a whole bunch of Data Mappers [5]. Nevertheless, I'm not calling it the Data Mapper layer for the reason that I also host the Unit of Work [5] in this layer. Usually the Unit of Work executes the stored procedure calls it has gathered information about from this very layer. So, as we will see, today's discussion is mainly about Data Mappers and Unit of Work.

The purpose of the Data Mapper [5] pattern is to map between a Domain Model [5] and the database, and the purpose of the Unit of Work [5] pattern is to gather information about all changes that should be persisted against the database later on in a use case.

Today and Tomorrow
I think a warning is in order before we get started. For now, there is a lot of code that has to be written in this layer. You can of course simply create a generator, but there will still be a lot of code. Tomorrow, when I've thought it through and decided how I want it, I will think about automating. I think I will try to develop an automated (non-handwritten code) solution for 80% of the cases and go for manual code in the more advanced situations. I will probably also use some code generation. The Generation Gap [6] pattern comes in handy here, until we have Partial Types as of V2 of the .NET Framework.

The purpose of the Generation Gap [6] pattern is to make it possible to regenerate code, without affecting the custom written code.

And as I always say, you can obviously opt for one of the commercial solutions instead. That will save you a lot of work.

OK, let’s dive into the code.

SaveOrder() in Service layer again

In part 4 [4], I showed a Service layer method for saving an order, which you can see again in Listing 1.

Public Sub SaveOrder (ByVal order As Order)

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date