The Darkside

Shedding light on things and stuff

 
  Home :: Contact :: Syndication  :: Login
  75 Posts :: 0 Stories :: 49 Comments :: 2 Trackbacks

Ads

Archives

Post Categories

Open Source Projects

Other Blogs

Introduction
In a previous post, I did a small intro to NHibernate, demonstrating the use of a persistence model for data storage. In this post, I will be taking the process a step further by making use of Castle ActiveRecord to eliminate the need for writing the hbm.xml files and greatly simplifying the syntax and coding needed for data mapping.
Castle ActiveRecord is a .Net implementation of the ActiveRecord pattern. More info on the design pattern can be found on Wikipedia (http://en.wikipedia.org/wiki/Active_record) and on Martin Fowlers site (http://www.martinfowler.com/eaaCatalog/activeRecord.html).
Downloads
ActiveRecordSampleApplication.zip [VS2005]
About the Sample Project
The sample project includes a SQL script for creating the DB. The extra tables and data are included for use in further articles. Also, you may wish to visit http://www.castleproject.org/activerecord/index.html for more information and downloads. The sample is based on the application used in the NHibernate post, but now makes use of ActiveRecord which in turn uses NHibernate instead of doing this directly.
ActiveRecord Attributes
Castle ActiveRecord makes use of attributes to do the mapping between your classes and data storage. This eliminates the need for the XML mapping files that were required when using only NHibernate. Here are a few examples of the most important attributes to get your mapping started.
The first is the [ActiveRecord] attribute, as seen here in an excerpt from “Contact.cs

[ActiveRecord]

public class Contact : ActiveRecordBase<Contact>

Also take note that the contact class inherits from ActiveRecordBase<T>. This also eliminates the need to have all the methods and properties marked as virtual, as seen with NHibernate.
The next attributes of interest are [PrimaryKey] and [Property]. These attributes allow you to define which property/column is your primary key, and indicate which properties in your class are columns in the table. ActiveRecord also support composite primary keys, however, single keys are preferred, even if it is added as a surrogate to the table. This greatly simplifies the handling of relations.

[PrimaryKey(Generator = PrimaryKeyType.GuidComb)]

public Guid ContactId

{

    get { return _contactId; }

    set { _contactId = value;}

 

}

[Property]

public string Title

{

    get { return _title; }

    set { _title = value; }

}

As in NHibernate, primary keys can have their generation strategy defined. Since the demo DB makes use of a GUID as the primary key for the tables, I’ve instructed active record to use the GuidComb generator. (There is also a Guid generator; however, GuidComb generates sequential Guids which make for faster insertions)
 
Another point of interest is that these attributes can also infer the column names, e.g. if the column in the table was actually “contact_title_main”, you could rewrite the attribute as:

[Property (Column="contact_title_main")]

public string Title

In the Contact class, another interesting attribute is [HasMany]. This greatly simplifies the notating of 1 to many relationships.

[HasMany(typeof(TelephoneNumber))]

public IList<TelephoneNumber> TelephoneNumbers

You will also notice that the TelephoneNumber class makes use of the [BelongsTo] attribute to indicate a many-to-one relationship.

[BelongsTo(Type = typeof(Contact), Column="ContactId")]

public Contact Contact

The are many other relation-defining attributes, including HasAndBelongsToMany, OneToOne and HasManyToAny.
Configuring ActiveRecord
As mentioned before, my first-choice configuration option is to include these details in “app.config”. A configuration section needs to be added.

<sectionname="activerecord" type="Castle.ActiveRecord.Framework.Config.ActiveRecordSectionHandler, Castle.ActiveRecord" />

The actual configuration is much the same as NHibernate, except for the outer tags.

<activerecord>

  <config>

    <add key="hibernate.connection.provider" value="NHibernate.Connection.DriverConnectionProvider"/>

    <add key="hibernate.dialect" value="NHibernate.Dialect.MsSql2005Dialect"/>

    <add key="hibernate.connection.driver_class" value="NHibernate.Driver.SqlClientDriver"/>

    <add key="hibernate.connection.connection_string" value="Server=SERVER;initial catalog=TelephoneBook;Integrated Security=SSPI"/>

    <add key="hibernate.show_sql" value="true"/>

  </config>

</activerecord>

 
I’ve made use of a static method in the ActiveRecordFactory class to initialise ActiveRecord. It makes use of the singleton ActiveRecordSectionHandler configuration information, as well as passes through the types that I want to initialise.
 

public static void Initialise()

{

    ActiveRecordStarter.Initialize(ActiveRecordSectionHandler.Instance, typeof(Contact), typeof(TelephoneNumber));

}

 
The Code
In the NHibernate example, I separated the domain objects (Contact and TelephoneNumber) from the persistence-related functionality, which differs slightly from the way ActiveRecord implements this.In ActiveRecord, the objects now have the CRUD functionality as inherited methods. It should be noted that this isn’t the only way that ActiveRecord implements this functionality. Should you be from the school of thought that prefers the separation of the model from the persistence methods, you can make use of the ActiveRecordMediator<T> class, which eliminates the need to extend the ActiveRecordBase class.
The ContactFactory class includes two list-retrieving methods, showing the ease of use of some of the filtering.

public static IList<Contact> GetListWithTitle(string title)

{

    return (Contact.FindAllByProperty("Title", title));

}

 
The rest of the code is largely unchanged so that you can compare the NHibernate example to the ActiveRecord example and make your own call.
Next
I will take a look at the query generation functionality that allows for plaintext styled queries in both the NHibernate and ActiveRecord examples.
 
posted on Sunday, September 02, 2007 9:02 AM
Comments have been closed on this topic.