Active Record is an architectural design pattern introduced by Martin Fowler in his 2003 publication.
The Active Record pattern is built on the concept of abstracting a database table into a class that adheres to OOP principles. In this pattern, each class instance represents a single table row, while the class itself provides methods implementing all CRUD operations. Such a class encapsulates all database interaction logic, offering an object-oriented interface for data manipulation. It's worth noting that this pattern inherently creates coupling between the class structure and the underlying database table.
Key Features:
1. Database Encapsulation: All database connection details and SQL queries are encapsulated within the class
2. Data Validation: The class implements validation rules before executing database operations
3. Object Properties: Direct mapping to table columns
4. Object Relationships: Handled through methods that implement database relationships (one-to-many, many-to-many, etc.)
While Delphi itself doesn't implement Active Record natively, DMVCFramework (https://github.com/danieleteti/delphimvcframework) provides a robust implementation of this pattern.
I recently found Active Record particularly useful when developing a small application to process and store JSON data in a database. Specifically, I needed to handle JSON files generated by Anthropic from Claude.AI conversation exports.
After analyzing the JSON structure, I designed the necessary database tables. To illustrate Active Record's features, I'll focus on a specific part of the implementation.
I started by creating the Chat 'header' table, then defined its corresponding Entity in Delphi:
The entity serves as an abstraction of our database table. Let's examine its structure:
We define a class inheriting from TMVCActiveRecord:
TChats = class(TMVCActiveRecord)
TMVCActiveRecord is the framework's base class that provides all necessary data interaction methods. The entity definition's key feature lies in its field declarations, each decorated with Custom Attributes that define their behavior:
[MVCTable('chats')]: This Custom Attribute specifies which database table the class abstracts
[MVCTableField('chat_uuid', [foPrimaryKey])]: This Custom Attribute binds class fields to physical database table attributes
We create similar entities for each database table we need to interact with.
The implementation then involves reading the JSON (using the JsonDataObjects library, also available in DMVCFramework), iterating through it, and persisting the data to the database.
This code creates a new database record, but what we've covered is just a basic introduction to Active Record in DMVCFramework. There are many more features available. For instance, how do we check if a chat has already been processed?
While this example uses RQL (Resources Query Language), we could alternatively use Active Record's built-in methods, such as querying by primary key.
This practical implementation demonstrates how Active Record significantly simplifies data persistence, allowing developers to focus on business logic rather than database access details. The combination of DMVCFramework and Active Record has made JSON data import and management remarkably straightforward and efficient.
Though this example is relatively simple, Active Record in DMVCFramework supports more complex scenarios, including entity relationships, custom validations, and advanced querying capabilities.
For further exploration, I recommend reviewing the DMVCFramework documentation, which provides comprehensive examples and advanced use cases. Understanding and properly implementing this pattern can substantially improve productivity when developing Delphi applications requiring database interaction.
#codinglikeacoder