Bootstrap Your App! : Data Access

Ok so we've covered the basics of getting a domain skeleton set up and ready to work. According to the principles of domain driven design the domain is the application, it should encapsulate all of the rules and logic inherent in our application.

I want to just mention that much of what I'm writing about in this series was taught to me by Eugene De Villiers, who also provided many of these code samples, and widely discussed with Pieter Koornhof. Both are excellent resources for Domain Driven Design discussion and explanations.

Repositories

In the real world we know that we will need to persist data, at least temporarily, and, though there has been a lot of debate around it's use, I like to use a generic repository to start with. In my view a generic repository allows for simple get and save methods for simple objects to be up and running very quickly, as your application grows your should add specialized repositories which take specific entity requirements into account and encapsulate entity-specific queries or persistence logic.

A Memory Repository

An in-memory repository is simply backed up by something like a list or dictionary which provides a quick, easy way to get up and running with testing in your app. It requires no setup and no data-store maintenance. As your entities grow and change it will simply work.

This might seem a bit silly but it makes early testing of business logic easy and speeds up development. This is also a great example of the benefits of abstraction, you can build and test your application and only decide on how you'd like to implement your data persistance right at the end of the project development, after the nature of the domain has revealed itself, and you can make the most informed decision about how best to persist your data.

A simple memory repository implementation can be found below:

    public class MemoryRepository<TEntity, TIdentifier> :  IRepository<TEntity, TIdentifier> where TEntity : class, IEntity<TIdentifier>
    {
        private readonly Dictionary<TIdentifier, TEntity> memoryStore;

        public MemoryRepository()
        {
            this.memoryStore = new Dictionary<TIdentifier, TEntity>();
        }

        public virtual TEntity Get(TIdentifier id)
        {
            if(!this.memoryStore.ContainsKey(id)) return null;

            TEntity entity = this.memoryStore[id];

            return entity;
        }

        public virtual TEntity Find(ISpecification<TEntity> specification)
        {
            Guard.AgainstNull(() => specification);

            TEntity entity = this.memoryStore.Where(x => specification.Predicate.Compile().Invoke(x.Value)).Select(x => x.Value).SingleOrDefault();

            return entity;
        }

        public virtual IEnumerable<TEntity> GetAll()
        {
            var entities = this.memoryStore.Values.ToList();

            return entities;
        }

        public virtual IEnumerable<TEntity> FindAll(ISpecification<TEntity> specification)
        {
            Guard.AgainstNull(() => specification);

            var entities = this.memoryStore.Where(x => specification.Predicate.Compile().Invoke(x.Value)).Select(x => x.Value);

            return entities;
        }

        public virtual TEntity Save(TEntity entity)
        {
            Guard.AgainstNull(() => entity);

            if(this.memoryStore.ContainsKey(entity.Id))
            {
                this.memoryStore[entity.Id] = entity;
            }
            else
            {
                this.memoryStore.Add(entity.Id, entity);                
            }

            return entity;
        }

        public virtual void Delete(TIdentifier id)
        {
            TEntity entity = this.Get(id);

            if (entity != null)
            {
                this.memoryStore.Remove(entity.Id);
            }
        }

        public virtual void Delete(TEntity entity)
        {
            Guard.AgainstNull(() => entity);

            this.Delete(entity.Id);
        }
    }

As with our other projects we will also need to have a container installer in order to make our repository available to the rest of our application:

public class DataAccessContainerInstaller : IWindsorInstaller  
    {
        public void Install(IWindsorContainer container, IConfigurationStore store)
        {
            container.Register(Component.For(typeof(IRepository<,>)).ImplementedBy(typeof(MemoryRepository<,>)).LifestyleSingleton()
                );
        }
    }

As you can see, this sets up Windsor to return a memory repository when we request the generic repository and this is the only thing we will need to change to switch the app over to our production data-persistance repository when we have it build.

An Entity Framework Repository

While the memory repository is useful for quick development we will eventually need to persist data in a more permanent way. As has been said before, the way you choose to persist your data should be determined by the nature of the application and not the prefences of the developers, the preference of the client or what storage mechanism you happen to have handy at the time. Sadly, a data persistance mechanism is often specified for an application or a system already exists with which we must integrate or which we must build on top of.

The following is an example of how you might implement a mechanism to access a Microsoft SQL Server database using Entity Framework:

    public class Repository<TEntity, TIdentifier> : IRepository<TEntity, TIdentifier> where TEntity : class, IEntity<TIdentifier>
    {
        protected DbContext DbContext { get; private set; }

        protected ObjectContext ObjectContext { get; private set; }

        public Repository(IUnitOfWork unitOfWork)
        {
            Guard.AgainstNull(() => unitOfWork);

            this.DbContext = unitOfWork.Context;
            this.ObjectContext = ((IObjectContextAdapter)this.DbContext).ObjectContext;
        }

        public virtual TEntity Get(TIdentifier id)
        {
            TEntity entity = this.DbContext.Set<TEntity>().Find(id);

            return entity;
        }

        public virtual TEntity Find(ISpecification<TEntity> specification)
        {
            Guard.AgainstNull(() => specification);

            TEntity entity = this.DbContext.Set<TEntity>().Where(specification.Predicate).SingleOrDefault();

            return entity;
        }
        ...

        public virtual TEntity Save(TEntity entity)
        {
            Guard.AgainstNull(() => entity);

            TEntity existing = this.Get(entity.Id);

            if (existing == null)
            {
                this.DbContext.Set<TEntity>().Add(entity);
            }
            else
            {
                string entitySetName = this.GetEntitySetName<TEntity>();
                this.ObjectContext.ApplyCurrentValues(entitySetName, entity);
            }

            this.ObjectContext.SaveChanges(SaveOptions.AcceptAllChangesAfterSave);

            TEntity saved = this.Get(entity.Id);

            return saved;
        }

        ...
    }

I have left out some of the the methods which need to implemented but you should be able to see what we're getting at here.

As you may have noticed, we're making use of a Unit of Work object which will be shared across any repositories we work with in the process of performing some action with the application. This will allow us to have properly atomic operations from the API layer downwards.

The interface for this unit of work looks like this:

    public interface IUnitOfWork : IDisposable
    {
        DbContext Context { get; }

        void Commit();

        void Rollback();
    }

And the implementation in this case is as simple as this:

    public class UnitOfWork : IUnitOfWork
    {
        private readonly DbContextTransaction transaction;
        private bool comitted;
        private bool rolledBack;
        private bool disposed;

        public DbContext Context { get; private set; }

        public UnitOfWork(DbContext context)
        {
            Guard.AgainstNull(() => context);

            this.Context = context;
            this.transaction = this.Context.Database.BeginTransaction();
        }

        public void Commit()
        {
            try
            {
                this.Context.SaveChanges();

                this.transaction.Commit();
            }
            catch(Exception)
            {
                this.Rollback();
                throw;
            }

            this.comitted = true;
        }

        public void Rollback()
        {
            this.transaction.Rollback();

            this.Context.Dispose();

            this.rolledBack = true;
        }

        public void Dispose()
        {
            this.Dispose(true);

            GC.SuppressFinalize(this);
        }


        private void Dispose(bool disposing)
        {
            if(!this.disposed)
            {
                if(disposing)
                {
                    if(!this.comitted && !this.rolledBack)
                    {
                        this.Commit();
                    }

                    this.Context.Dispose();
                }
            }
            this.disposed = true;
        }
    }

If you would like more information about implementing IDisposable you can find it here.

As you can see the unit of work requires a DbContext object to function and we would like to control the creation of this object carefully. In order to acheive this we will be using a factory class and telling Castle Windsor to use it.

The factory interface looks like this:

    public interface IUnitOfWorkFactory
    {
        IUnitOfWork CreateUnitOfWork();
    }

And the implementation looks like this:

    public class UnitOfWorkFactory : IUnitOfWorkFactory
    {
        private readonly string connectionString;

        public UnitOfWorkFactory(string connectionString)
        {
            this.connectionString = connectionString;
        }

        public IUnitOfWork CreateUnitOfWork()
        {
            DataContext context = DataContext.Create(this.connectionString);
            IUnitOfWork unitOfWork = new UnitOfWork(context);

            return unitOfWork;
        }
    }

This in turn relies on the DataContext which handles the configuration and creation of our DbContext:

[DbConfigurationType(typeof(DatabaseConfiguration))]
    public class DataContext : DbContext
    {
        private const string defaultProvider = "System.Data.SqlClient";

        protected DataContext(DbConnection connection)
            : base(connection.ConnectionString) {}

        public static DataContext Create(string connectionString)
        {
            return Create(connectionString, defaultProvider);
        }

        public static DataContext Create(string connectionString, string providerInvariantName)
        {
            DbConnection connection = CreateConnection(connectionString, providerInvariantName);
            DataContext context = new DataContext(connection);

            return context;
        }

        private static DbConnection CreateConnection(string connectionString, string providerInvariantName)
        {
            DbProviderFactory factory = DbProviderFactories.GetFactory(providerInvariantName);
            DbConnection connection = factory.CreateConnection();

            if(connection != null)
            {
                connection.ConnectionString = connectionString;
            }

            return connection;
        }
    }

Now we will need to tell Windsor to use this factory and this is accomplished by replacing the code in the data access installer with this:

container.Register(  
                Component.For(typeof(IRepository<,>)).ImplementedBy(typeof(Repository<,>)).LifestyleSingleton(),
                Component.For<IUnitOfWorkFactory>().ImplementedBy<UnitOfWorkFactory>()
                         .UsingFactoryMethod(() => new UnitOfWorkFactory("<ConnectionStringGoesHere>")),
                Component.For<IUnitOfWork>().ImplementedBy<UnitOfWork>()
                         .UsingFactoryMethod(k => k.Resolve<IUnitOfWorkFactory>().CreateUnitOfWork())
                         .LifestylePerWebRequest()
             );

This tells Windsor that we would like to use our unit of work factory to create new units of work. I have chosen here to tell Windsor to scope the lifestyle of the unit of work to a web request but you should decide what is most appropriate to your application.

Mapping

When moving things from your domain to your persistence medium of choice, and vice versa, you will need to map them to the underlying data store.

There are cases that seem as though they will not require this, such as the use of a document database or simple JSON serialization, but we will want to have some control over the process of mapping things from our data to our domain. This will allow us to handle type forwarding, name changes and the like.

We also might find that we need to map a nice, properly named domain to an ugly, badly named existing data store.

In most cases you will probably want to write simple, custom mappers for this as Automapper configurations for this sort of work can get out of hand quickly. In the case of Entity Framework (version 6 or higher), however, there is a very nice way of mapping tables directly to domain entities.

In the DataContext class above we need to add this code to register our custom mappings:

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //pick any of your mapping types to go here to locate the assembly
            Type mappingType = typeof(TestEntityMapping);
                        modelBuilder.Configurations.AddFromAssembly(Assembly.GetAssembly(mappingType));

            base.OnModelCreating(modelBuilder);
        }

By overrriding the OnModelCreating method of the DataContext we can specify custom mappings for our objects instead of the default EF behaviour which is to expect things to be named exactly the same.

We are using one of our mapping classes, TestEntityMapping, to tell EF which assembly to inspect to find our mapping classes and it looks like this:

    public class TestEntityMapping : EntityTypeConfiguration<TestEntity>
    {
        public TestEntityMapping()
        {
            this.ToTable("TestEntities", "tst");

            this.HasKey(p => p.Id);

            this.Property(p => p.Name)
                .HasColumnName("CountryName")
                .HasMaxLength(100)
                .IsRequired();

            this.Property(p => p.DisplayName)
                .HasMaxLength(150)
                .IsOptional();

            this.Ignore(p => p.OtherValue);

            this.Ignore(x => x.Id);
        }
    }

As you can see, this allows us to map each property of our domain entity to the data store explicitly. We can specify the table it maps to, contstraints on the properties and many others.

You can find more information on this here and here.

This should give your project at least a temporary way to persist your data and it shows how easy it can be to switch between persistence implementations when you abstract things properly.

Please check back soon for the next post in this series where I'll be discussing the API layer and allowing access to our app!