Programming Microsoft ASP.NET 4 - Dino Esposito [307]
The real shift toward an object-oriented design starts when you envision the application as a set of interrelated objects—which is a different thing than using objects to perform data access and calculations. An object-based model has two main levels of complexity—simple and not-so-simple. A good measure of this complexity is the gap between the domain’s object model and the relational data model you intend to create to store your data.
A simple model is when your entities map closely to tables in the data model. A not-so-simple model is when some mapping is required to load and save domain objects to a relational database. The Active Record pattern is your choice when you want an object-oriented design and when your domain logic is simple overall.
In Active Record, each class essentially represents a record in a database table: the classes usually have instance methods that act on the represented record and perform common operations such as save and delete. In addition, a class might have some static methods to load an object from a database record and it might perform some rich queries involving all records. Classes in an Active Record model have methods, but these methods are mostly doing Create, Read, Update, Delete (CRUD) operations. There’s nearly no domain logic in the classes of an Active Record model, even though nothing prevents you from adding that.
An aspect that makes Active Record so attractive to developers is its extreme simplicity and elegance and, just as significantly, the fact that in spite of its simplicity it works surprisingly well for a many Web applications—even fairly large Web applications. I wouldn’t be exaggerating to say that the Active Record model is especially popular among Web developers and less so among Windows developers.
Beyond the simplicity and elegance of the model, available tools contribute significantly to make Active Record such a popular choice. Which tool should you use to implement an Active Record model?
LINQ-to-SQL is definitely an option. Fully integrated in Visual Studio 2008 and later, LINQ-to-SQL allows you to connect to a database and infer a model from there. As a developer, your classes become available in a matter of seconds at the end of a simple wizard. In addition, your classes can be recreated at any time as you make changes, if any, to the database. In terms of persistence, LINQ-to-SQL is not really a canonical Active Record model because it moves persistence to its internal DAL—the data context. LINQ-to-SQL incorporates a persistence engine that makes it look like a simple but effective Object/Relational Mapper (O/RM) tool with full support for advanced persistence patterns such as Identity Map and, especially, Unit of Work.
Castle Active Record is another framework that has been around for a few years and that offers a canonical implementation of the Active Record pattern. Finally, an emerging framework for Active Record modeling is SubSonic. (See http://www.subsonicproject.com.)
Unlike Castle Active Record, SubSonic can generate classes for you but does so in a way that is more flexible than in LINQ-to-SQL: it uses T4 templates. A T4 template is a .tt text file that Visual Studio 2008 and later can process and expand to a class. If you add a T4 template to a Visual Studio project, it soon turns it into a working class. This mechanism offers you an unprecedented level of flexibility because you can modify the structure of the class from the inside and not just extend it with partial classes as in LINQ-to-SQL, and it also removes the burden of writing that yourself as you must do with Castle Active Record.
The Domain Model Pattern
In the Domain Model pattern, objects are aimed at providing a conceptual view of the problem’s domain. Objects have no relationships with the database and focus on the data owned and behavior to offer. Objects have both properties and methods and are not responsible for their own persistence. Objects are uniquely responsible