Castle’s ActiveRecord: Not for the Domain Purist in you…

 I finally “broke down” and began using ActiveRecord just to try it out. Here’s the tutorial that I used. Now, don’t get me wrong - ActiveRecord is built on top of NHibernate and it’s one of the fastest ways to start working with your persistence layer.

So what’s the problem?

Well, it’s this:

using Castle.ActiveRecord;

namespace Foo.Domain

{

    [ActiveRecord]

    public class Dealer : ActiveRecordBase<Dealer>

    {

        private int id;

        private string contactFirstName;

        private string contactLastName;

        private string businessName;

        private Address address;

        private string email;

        private PhoneNumber contactPhoneNumber;

        private PhoneNumber faxNumber;

 

        public Dealer()

        {

            address = new Address();

            contactPhoneNumber = new PhoneNumber();

            faxNumber = new PhoneNumber();

        }

 

        [PrimaryKey(PrimaryKeyType.Identity, "DealerId", Access=PropertyAccess.NosetterCamelcase)]

        public int Id

        {

            get { return id; }

        }

 

        [Property]

        public virtual string BusinessName

        {

            get { return businessName; }

            set { businessName = value; }

        }

 

        [Property]

        public virtual string ContactFirstName

        {

            get { return contactFirstName; }

            set { contactFirstName = value; }

        }

 

        [Property]

        public virtual string ContactLastName

        {

            get { return contactLastName; }

            set { contactLastName = value; }

        }

 

        [Property]

        public virtual string Email

        {

            get { return email; }

            set { email = value; }

        }

 

        [Nested("ContactPhoneNumber")]

        public virtual PhoneNumber ContactPhoneNumber

        {

            get { return contactPhoneNumber; }

            set { contactPhoneNumber = value; }

        }

 

        [Nested("FaxNumber")]

        public virtual PhoneNumber FaxNumber

        {

            get { return faxNumber; }

            set { contactPhoneNumber = value; }

        }

 

        [Nested]

        public virtual Address Address

        {

            get { return address; }

            set { address = value; }

        }

    }

}

Those attributes are tagging persistence concerns all over my domain object!! The class also inherits from ActiveRecordBase<T>, a persistence focused class having nothing to do with the domain itself.

Finally, the class if forced to expose a setter for the value objects: ContactPhoneNumber, FaxNumber, and Address. The class should not have to allow external objects to directly set properties that access value objects. An external object can directly overwrite the value object references managed by my Dealer aggregate. (Please tell me I’m wrong on this.)

Of course, these are known drawbacks to using AR and it’s really only a concern for domain purists out there (who me?). All in all, ActiveRecord is great for getting started with simple domains that map fairly easily to their relevant database tables.

Here’s all I had to do in my test to get AR Unit Testing working.

1. I borrowed and slightly modified the unit testing base class, AbstractModelTestCase, from this article. I modified it to support usage of NDbUnit (the original, not my modified version):

        [SetUp]

        public virtual void Init()

        {

            sqlDbUnit = new SqlDbUnitTest(GetConnectionString());

 

            PrepareSchema();

            CreateScope();

        }

 2. I wrote my specifications utilizing an NDbUnit schema and data file. It was as easy as:

using Foo.Domain;

using NUnit.Framework;

using NDbUnit.Core;

 

namespace Specifications.Foo.Domain.ActiveRecord

{

    [TestFixture]

    public class ADealerListWithOneDealer : AbstractModelTestCase

    {

        protected override void PrepareSchema()

        {

            sqlDbUnit.ReadXmlSchema(@”….SchemasDealerSchema.xsd”);

            sqlDbUnit.ReadXml(@”….TestDataTestDataForADealerListWithOneDealer.xml”);

 

            sqlDbUnit.PerformDbOperation(DbOperationFlag.CleanInsert);

        }

 

        [Test]

        public void ShouldHaveASizeOfOne()

        {

            FlushAndRecreateScope();

            Dealer[] dealers = Dealer.FindAll();

            Assert.AreEqual(1, dealers.Length, “Should have a length of 1, given the test data.”);          

        }

    }

}

As you can see, almost no persistence code was written to accomplish this trivial bit of work.

Repositories

Repositories are not explicit using the AR method of persisting entities, as shown above. Persistence concerns are directly associated with the entity (via Find(), FindAll(), etc). Ayende has an Active Record repository implementation in his Rhino Commons library. The SVN url is https://svn.sourceforge.net/svnroot/rhino-tools/trunk/ and the code can be found under rhino-commons/Rhino.Commons/Repositories.

Ayende’s ARRepository implementation appears to be a way around inheriting from ActiveRecordBase<T>, but I’m not sure. Does anybody else know?

Related Articles:

Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Nelson Montalvo

I’m a software developer who loves .NET, Agile methodologies, Test Driven Design, Domain Driven techniques, and open source tools. Don’t get me wrong, I also like to use a thing or two that Microsoft creates besides .NET itself. :) In my “spare time” (when is that, anyways?) I like riding my motorcycle (http://sportbike.nmonta.com), reading, watching movies (lots of movies), working out, and hanging out (good conversation, good beer, good times). Look me up in Facebook, Linked In or Plaxo. My personal code blog is http://codemonkey.nmonta.com.
This entry was posted in Castle, Domain Driven Design, NHibernate. Bookmark the permalink. Follow any comments here with the RSS feed for this post.

4 Responses to Castle’s ActiveRecord: Not for the Domain Purist in you…

  1. 1/ You don’t need to inherit from ARBase
    2/ You can specify that you want the OR/M to go directly against the fields, instead of using properties.
    3/ I don’t have a problem with the properties, they are not actionable, they are declarative, and I find that it is usually faster than writing the info in XML.

  2. agilejoe says:

    It’s not that I am am totally against active record. I am sure it has it’s place in certain applications. But from an enterprise perspective the fact that I am decorating my domain with persistence layer artifacts, just doesn’t sit well with me. But if RAD is what you want then AR is the way to go.

    Cheers!

  3. mawi says:

    Sidenote: Why use an active record implementation if you dislike the architectural *pattern*?

    (The PoEEE summary of the pattern:
    “An object that wraps a row in a database table or view, encapsulates the database access, and adds domain logic on that data.”)

  4. nmonta76 says:

    I was experimenting with ActiveRecord, an implementation of the pattern built on top of NHibernate.

    As it is, the pattern itself can occasionally serve the purpose from a DDD point of view. Afterall, I can have domain objects that map directly to tables, right? And my domain objects can – under the covers – deal with the database. As long as that work is not directly exposed to my domain in some form such as domainObject.InsertIntoSqlDatabase().

    However, tagging my domain object itself with persistence concerns does bother me. The cool thing is that ActiveRecord (the tool) does provide the ActiveRecordMediator object. This allows for us to take more of a repository approach. I did not make that clear in my last statement. Sorry.