Archive

Posts Tagged ‘Active Record’

Domain-Driven Design with Linq & ORM – Part 2

June 19th, 2008 stiiifff 2 comments

In my last post about DDD & Linq (1.5 month ago … oops), I showed the following piece of code:

ServiceLocator.Register<IUnitOfWorkFactory, NHibernateUnitOfWorkFactory>();

using (UnitOfWork.Start())
{
    ITransaction tx = UnitOfWork.Current.BeginTransaction(IsolationLevel.ReadCommitted);
    try
    {
        IRepository<Customer> cr = UnitOfWork.Current.GetRepository<Customer>();
        Customer customer = cr.FindOne(c => c.Id == "AROUT");
        customer.Address = "125 Hanover Sq.";
        cr.Save(customer);
        tx.Commit();
    }
    catch
    {
        if (tx != null) tx.Rollback();
    }
    finally
    {
        if (tx != null) tx.Dispose();
    }
}

After thinking about it, refactoring it 10 times, I sat down this morning and finally got it the way I wanted (don’t ask me why it took so long lol):

// Configure your favorite IoC container:
// - Register an IUnitOfWorkFactory
// - Register an IRepositoryFactory
// - Register a generic IRepository<TEntity>
//   (your container must support open generic types).
// - Configure your container to use the IRepositoryFactory
//   to create instances of the IRepository<TEntity> component
//   (your container must support factories).
// Once your IoC container is set up, configure it as the ServiceProvider
// (must implement the IServiceProvider interface or use a wrapper) for the ServiceLocator helper
ServiceLocator.ServiceProvider = container;

// Start a unit of work
using (IUnitOfWork uow = UnitOfWork.Start())
{
    // Get an instance of repository
    IRepository<Customer> cr = ServiceLocator.GetService<IRepository<Customer>>();

    // Retrieve data with a Linq query
    Customer customer = cr.FindOne(c => c.CustomerID == "AROUT");

    // Modify retrieved entity
    customer.Address = "000 Hanover Sq.";

    // Ask repository to save changes
    cr.Save(customer);

    // Mark the unit of work as complete to propagate changes to data source
    uow.Complete();
}

The re-worked IRepository<T> looks like this:

public interface IRepository<TEntity> : IDisposable where TEntity : class
{
    long Count();
    long Count(Expression<Func<TEntity, bool>> predicate);
    void Add(TEntity entity);
    void Add(IEnumerable<TEntity> entities);
    void Remove(TEntity entity);
    void Remove(IEnumerable<TEntity> entities);
    void RemoveAll();
    void RemoveAll(Expression<Func<TEntity, bool>> predicate);
    void Save(TEntity entity);
    void Save(IEnumerable<TEntity> entities);
    TEntity FindOne(Expression<Func<TEntity, bool>> predicate);
    IEnumerable<TEntity> FindAll();
    IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> predicate);
    IQueryable<TEntity> QueryAll();
    IQueryable<TEntity> QueryAll(Expression<Func<TEntity, bool>> predicate);
}

I think it looks better ;) I currently have UoW & Repository factories for the following ORM:

  • NHibernate
  • ActiveRecord
  • LinqToSql
  • EntityFramework

The code is still very experimental, relies a lot of Castle Project‘s libraries (some might view it as a pro, others a con …), and I unfortunately don’t have much time to work more on it. If there is any interest for it, I might drop it online in its current state (basic samples, no unit test, code analysis spitting out a lot of warnings).

Feedback is welcomed. :)

Possible Improvements:

  • For simplification purpose, I might remove the dependency to a ‘ServiceProvider‘ and instead define a simple ‘UnitOfWork.Configure‘ method where we can specify the type of the IUnitOfWorkFactory & IRepositoryFactory.
  • Should the IUnitOfWork interface expose a ‘GetRepository<TEntity>‘ method to get rid of the ugly static call to ‘ServiceLocator.GetService<IRepository<T>>‘ ?

ActiveRecord & Repository pattern

May 19th, 2008 stiiifff 1 comment

Hammett has a post where he, among others, advises:

I don’t encourage people to use AR with the AR base class. Use the
ARMediator and use the repository pattern or a dao pattern to increase
isolation and testability.

Yes ! It seems not many people knew it (I did, I'm a Reflector addict lol) but you can use ActiveRecord without base classes for your entities (ActiveRecordBase), just use the [ActiveRecord] attribute.

That way, you get:

  • Attribute-based mapping declaration (instead of manual edition of NHibernate mapping files, which can be cumbersome).
  • Well-tested plumbing code like session & transaction scopes.
  • Easy querying through ActiveRecordMediator static methods, instead of direct use of NHibernate ISession.

Now, if you want the best ORM experience in a DDD-context:

  • Use the Repository pattern, to get an additional layer of abstraction between your application code & your particular ORM.
  • Use Linq queries in your repositories, for rich ORM-independent querying capabilities (your ORM has to support Linq of course).

I've been refactoring & cleaning up some code lately, I will soon drop the first draft of Yoot.DomainDriven, a non-intrusive framework for pragmatic Domain-Driven Design with nice abstraction of Units of work & Linq-friendly repositories, and implementations for mainstream ORM tools. :)

Domain-Driven Design with Linq & ORM

May 1st, 2008 stiiifff 2 comments

We all now that an ORM plays an important role in a DDD architecture … but it would be nice if we could write our Domain Model without being tightly coupled to our favorite ORM tool, especially the code we write in Repositories. Thanks to Linq, we already have a way to abstract our queries (our ORM 'just has to' support Linq, anyway that's a requirement for a good ORM nowadays). The other thing we should be able to abstract is the object, specific to each ORM, that is the interface with the persistence layer, that keeps track of the changes on entities, the 'context' or the 'session' object.

Well, most ORM tools are implementing similar Patterns, namely UnitOfWork, IdentityMap, LazyLoad … so it is fair to assume that it should be possible to build an abstract layer that would allow us to work at a higher level, and have providers for our favorite ORM tools.

Here is a sample from some early code I wrote:

ServiceLocator.Register<IUnitOfWorkFactory, NHibernateUnitOfWorkFactory>();

using (UnitOfWork.Start())
{
    ITransaction tx = UnitOfWork.Current.BeginTransaction(IsolationLevel.ReadCommitted);
    try
    {
        IRepository<Customer> cr = UnitOfWork.Current.GetRepository<Customer>();
        Customer customer = cr.FindOne(c => c.Id == "AROUT");
        customer.Address = "125 Hanover Sq.";
        cr.Save(customer);
        tx.Commit();
    }
    catch
    {
        if (tx != null) tx.Rollback();
    }
    finally
    {
        if (tx != null) tx.Dispose();
    }
}

The Repository interface, which makes heavy use of Linq to express query criterions, looks like this:

public interface IRepository<TEntity> where TEntity : class
{
    long Count();
    long Count(Expression<Func<TEntity, bool>> predicate);
    void Delete(TEntity entity);
    void Delete(IEnumerable<TEntity> entities);
    void DeleteAll();
    void DeleteAll(Expression<Func<TEntity, bool>> predicate);
    void Save(TEntity entity);
    void Save(IEnumerable<TEntity> entities);
    TEntity FindOne(Expression<Func<TEntity, bool>> predicate);
    IEnumerable<TEntity> FindAll();
    IEnumerable<TEntity> FindAll(Expression<Func<TEntity, bool>> predicate);
    IQueryable<TEntity> ProjectAll();
    IQueryable<TEntity> ProjectAll(Expression<Func<TEntity, bool>> expression);
}

Wanna use LinqToSql or EntityFramework instead of NHibernate … well, that’s easy, just change the first line to:

ServiceLocator.Register<IUnitOfWorkFactory, LinqToSqlUnitOfWorkFactory>();

or

ServiceLocator.Register<IUnitOfWorkFactory, EntityFrameworkUnitOfWorkFactory>();

Nice isn’t it ? ;)
We can also have:

ServiceLocator.Register<IUnitOfWorkFactory, ActiveRecordUnitOfWorkFactory>();

or

ServiceLocator.Register<IUnitOfWorkFactory, EussUnitOfWorkFactory>();

Well, I think you get the point.
So, what you think ? Suggestions & remarks are welcome.

“Not invented here” disclaimer: This code is largely inspired and based on code from Castle Project & Rhino.Commons. I just generalized it.

“Pre-Pre-Pre-Pre-Pre Alpha code” disclaimer: This code is quite experimental, it is not (yet) fully unit-tested and doesn’t support (yet) all the capabilities of the different ORM tools presented here.