Applying the Data Mapper Pattern
A data mapper (DM) object does the magic of loading raw data extracted from tables into in-memory objects that closely map to a higher level, entity-relationship data model. The DM pattern is excellent for sophisticated domain logic where the physical structure of data must be abstracted to straighten coding, simplify reading, and guarantee cost-effective maintenance. A highly sophisticated logic has typically a number of additional requirements such as multi-database support and serious unit-testing. In both cases, different deployments of the system, or different steps during the development cycle, may require that the whole data-mapper layer be replaced to apply a different logic, target a different database, or just for unit-testing purposes. The more abstraction you have and the more stratified the system is, the better for you and your customers.
Admittedly, the DM pattern may look a bit too complex at times and is certainly a viable option for rich and complex systems. A simpler variation, ideal for quite simple logic, is the Active Record pattern. (See the "Active Record
In a DM scenario, you create a bunch of classes for each entity in the abstract data model for the application. You create an entity class, perhaps a type-safe collection class, and a manager class to provide public entry points in the DAL. Listing 5
details some sample code.
|Figure 7: Architecture of a multi-tier application with patterns.|
What about the implementation of the methods in the EmployeeManager class? No matter how much abstraction you put in your design, at some point you need to dirty your hands with connection strings, ADO.NET commands, transactions and the like. You can certainly insert this code directly in the body of the EmployeeManager's methods. A better approach, though, is using an intermediate set of classes based on the TDG pattern to do just this. Figure 7
shows the overall schema.
The idea is, the presentation layer creates an instance to the manager class of a given entity (say, employee). On one end, the manager class exposes high-level objects to the presentation layer; on the other end, it connects to the underlying DAL for physical data access. There might be various layers between the manager and the DAL. For the greatest flexibility, you might want to use a replaceable factory and target different databases.
Invoked from the presentation layer, the manager class may, in turn, instantiate a data access provider factory class. This class will read from the configuration file information (class and assembly) about the factory class to use to create data providers for each of the supported entities (employee, customer, product, order).
Each factory class implements a contracted interface that basically counts a method to return the data provider for the various entities. Finally, the "data provider" implements an interface that matches the methods on the manager class and uses the TDG pattern to get and set physical data on a particular database.
With this schema, by simply changing an entry in the configuration file you make the whole system work on a totally different database. You have classesthe data provider-where you can write optimized database codeand thanks to contracted interfaces you don't break upper tiers.
Applying the Table Data Gateway Pattern
In complex systems, you combine the TDG pattern with DM and Factory to create an extremely flexible and extensible solution. Here I must remark upon two architectural aspects. First, you can write straight ADO.NET code directly in the methods of the manager class, get rid of factories, and obtain a pure DM solution. Likewise, you can write a pure TDG solution as discussed in a moment and obtain a Visual Studio 2005-like solution. A combination of patterns versus single patterns is an individual and project-specific choice and trade-off.
In the TDG jargon, the gateway is an object that wraps access to a database table. You play with one object which handles all table rows. Methods on the gateway class typically return ADO.NET objects; input arguments are listed as individual values and are not grouped in containers like entity classes. Here's an example:
Public Class EmployeeGateway
Public Function Find(ByVal id As Integer) _
Public Function FindAll() As DataTable
Public Sub Save(ByVal id As Integer, ...)
Public Sub Insert(...)
Public Sub Delete(ByVal id As Integer)
The more you add methods here, the more the TDG model evolves into a DM model. If you compare this abstract definition of a gateway with the table adapter class discussed earlier in the article, you find a clear match between the two.
Drawing the Bottom Line
The first consideration that springs to mind is that patterns are sometimes way too abstract, while your ultimate goal as a developer is writing concrete code that actually works. Patterns, therefore, should be your guide; they are not necessarily they the Word
that inspires you in each and every action and decision.
|Make choices based on your preferences and level of comfort with a given approach, but don't be afraid to try new things. |
It is essential that you make choices based on your preferences and level of comfort with a given approach. At the same time, though, don't be afraid to try a new thing and a more structured approach to complex issues. It may happen that you like it. Keep things simple but never simpler than needed and be ready and prompt to recognize and handle complexity. Be agile and nimble especially in a complex context; this may be hard to do, but it is too often just the difference that stands between success and failure.
The wizards of the Visual Studio 2005 data designer generate code that works according to a classic TDG approach. There's nothing bad with it and nothing new or esoteric. The key with wizards is knowing what they do in order to figure out what you can do about it. To fully understand what the Visual Studio 2005 data designer does, a tour of enterprise data access design patterns is essential.
This article first explained internals of Visual Studio 2005 code and then put that into a pattern perspective tracing a hopefully clear route for further enhancements. The Visual Studio 2005 data designer does create an architecturally valid DAL but you have to understand its code and be ready to edit it. The pattern in use, though, may not be appropriate for sophisticated applications. Now you know it; back on to Visual Studio 2005 and enjoy it with reason!