Daily Archives: 1 February 2014

A Unit of Work with Repositories Underpinned by DbContext – The DAL

An index of the HomeLibrary application posts can be found here.

I want to have a quick discussion about data access, as I have already re-factored this code in the HomeLibrary application. Originally, I just put in place a couple of simple repositories which looked like this:
Generalised Base Class

public abstract class RepositoryBase<T, TCxt> : IDisposable
	where T : class
	where TCxt : DbContext, new()
{
	public DbContext Context;
	public DbSet<T> Items;

	protected RepositoryBase()
		: this(new TCxt())
	{
		
	}

	protected RepositoryBase(TCxt context)
	{
		Context = context;
		Items = Context.Set<T>();
	}

	public T Create()
	{
		CheckDisposed();
		return Items.Create();
	}

	public void Add(T item)
	{
		CheckDisposed();
		Items.Add(item);
		Context.SaveChanges();
	}

	public T GetById(int id)
	{
		CheckDisposed();
		var set = Items.Find(id);
		return set;
	}

	public void Remove(T item)
	{
		CheckDisposed();
		Items.Remove(item);
		Context.SaveChanges();            
	}

	public void Update(T item)
	{
		CheckDisposed();

		var entry = Context.Entry(item);
		if (entry.State == EntityState.Detached)
		{
			Items.Attach(item);
			entry.State = EntityState.Modified;
		}
		Context.SaveChanges();            
	}
	
	public IList<T> GetAll()
	{
		CheckDisposed();
		return Items.ToList();
	}

	public abstract void CheckDisposed();

	public void Dispose()
	{
		if (!Context.TryDispose()) return;
		Context = null;
		Items = null;
	}
}

Domain-centric Repositories would Inherit from the Base Class

public class BookRepository : RepositoryBase<Book, HomeLibraryContext>, IBookRepository 
{
	public BookRepository()	{ }

	public BookRepository(HomeLibraryContext ctx) 
		: base(ctx)
	{ }

	public override void CheckDisposed()
	{
		if (Context == null)
		{
			throw new ObjectDisposedException("BookRepository");
		}
	}
}

I had a feeling there would be some better stuff out there which facilitated the repository-style access to the data via the DbContext. After a bit of searching, I stumbled upon this answer at stackoverflow. You can go there to read the code if you like (or here for my version), as it is quite large and not practical for me to repeat here.

It uses a unit of work to centralise access through a number of repositories. I liked the idea of this and when I went through the code, I recognised that it was quite sophisticated and written by someone who had really thought it through (and probably incorporated some hard learnt lessons). I made a couple of changes which I preferred, as I don’t just accept someone else’s code without scrutiny. I tagged that revision of the source DataAccessAndDomain_1.1, so it is available to download or read online.

This is definitely overkill for a simple book-lending application. However, I want to endeavour to use enterprise best practices for this sample application.