Fun with Data Access
Nearly every software application I've written in the last five years, web or otherwise, has interacted with an underlying relational data-store, which in turn is nearly always SQL Server. This might explain my preoccupation with data access patterns.
After following a discussion regarding the merits of MVC started by Chris Anderson, I started to question my own use of design patterns. I've played around with object mappers such as Microsoft's ObjectSpaces. I've used DataSets to hold everything. I've passed XML to and fro. The data access method of choice I eventually settled on was custom data access classes with custom entity classes and the abstract factory pattern.
It goes something like this:
Start by defining one or more entity classes (Customer for example). Then define a set of data access interfaces for each entity (ICustomerDao). These interfaces define the basic CRUD methods and accept/return your custom entities. After the interfaces are defined, you define a factory interface that serves as the abstract data access factory (IDaoFactory). With the entities and interfaces in place, you can now write your data-store specific concrete implementations of the data access interfaces (SqlServer.CustomerDao) and the factory (SqlServer.DaoFactory). The idea is that some day when your data-store changes you can just write a concrete implementation for that data store (Oracle.CustomerDao, Oracle.DaoFactory) and just use the appropriate factory. You can even use the Activator class to dynamically determine which factory to use based on a configuration file setting.
The problem with this approach is that it’s a lot of work. I'm guessing 2 hours/entity. You’ve written all of your entities, interfaces, and concrete implementations before you’re even dealing with any business logic. I know I'm lazy, but that’s a lot of code to write for your average in-house expense tracking application.
Today I decided to explore the other end of the spectrum… dragging a table on to the Visual Studio .NET Schema designer, creating a typed DataSet from the schema, and using the DataAdapter wizard to automagically create a bunch of CRUD that supports a version of optimistic concurrency. Time elapsed: 3 minutes.
Do I get the feeling of satisfaction of knowing that I’m writing a highly extensible, maintainable application? I'm not sure yet. Do I get the best performance for my buck? Not really. What I do get, though, is an extra eight hours to read up on Remoting, WS-*, and other topics of interest from my favorite bloggers.