Rebuilding Compiled Experience
Most of the time I do any database interaction I follow a "Unit of Work" pattern. This allows good control over when work is submitted to the database, in terms of the Entity Framework, the Unit of Work controls the lifetime of the ObjectContext.
The implementation is pretty simple, we have a UnitOfWork static class that provides easy access to the current UOW as well as starting and disposing. We then have our IUnitOfWork which is where the work of accessing repositories and submitting changes to the database will be done. We then implement that with EntityUnitOfWork.
I like to follow the approach of "Unit of Work per Request" for web applications and usually handle this with an IHttpModule that manages it for me. However for MVC I wanted to try something different. One of the reasons I didn't like Module approach for MVC was that the UnitOfWork was still active during the rendering of the View. This meant that any complex lazy loaded queries could still be evaluated which could leave me vulnerable to N+1 problems.
public class UnitOfWorkAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
UnitOfWork.Start();
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if(UnitOfWork.IsStarted)
UnitOfWork.Dispose();
}
}
In the end I created a UnitOfWorkAttribute which inherits from ActionFilterAttribute, this enables me to dispose of the current unit of work after the action is completed but before the view is processed. It means that if the view triggers anything that causes database access it throws an error. I can now enforce the convention that all data must be loaded by the action.
[HttpPost, UnitOfWork, ActionName("sign-in")]
public ActionResult SignIn(SignInViewModel details, string returnUrl)
Rebuilding Compiled Experience
A long time ago I wrote a few posts about using "Domain Driven Design"-esque repositories using Linq to SQL ("Domain Driven Design Repositories in Linq to SQL"). I still use that general pattern with a few tweaks with extra layer of a "Unit of Work" to manage context lifetimes. I'm using this rebuild as a chance to play with Entity Framework 4 and so need to implement the appropriate interfaces all over again. The only major functionality change will be bringing in support for Entity Frameworks "Include".
I'm not going to go over the full pattern here, just the new parts for Entity Framework, the IRepository interface has changed that GetAll returns an interface IQuery which is pretty much the IQueryable interface with the Include method.
The implementations for IQuery and IRepository are as follows.
public class EntityRepository<T> : IRepository<T> where T : class
{
private readonly ObjectSet<T> objectSet;
public EntityRepository(ObjectSet<T> objectSet)
{
this.objectSet = objectSet;
}
public IQuery<T> GetAll()
{
return new EntityQuery<T>(objectSet);
}
public void Save(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
objectSet.AddObject(entity);
}
public void Update(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
objectSet.Attach(entity);
}
public void Delete(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
objectSet.DeleteObject(entity);
}
}
public class EntityQuery<T> : IQuery<T>
{
private readonly ObjectQuery<T> query;
public EntityQuery(ObjectQuery<T> query)
{
this.query = query;
}
public IQuery<T> Include(string path)
{
return new EntityQuery<T>(query.Include(path));
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IEnumerable<T>)query).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)query).GetEnumerator();
}
Expression IQueryable.Expression
{
get
{
return ((IQueryable)query).Expression;
}
}
Type IQueryable.ElementType
{
get
{
return ((IQueryable)query).ElementType;
}
}
IQueryProvider IQueryable.Provider
{
get
{
return ((IQueryable)query).Provider;
}
}
}
The actual Repository that gets used by the domain layer simply delegates all it's work back to a internal repository based off the current unit of work. This is important section because it decouples the domain repository from repository doing the actual work and allows me to change the underlying data source if necessary.
public class Repository<T> : IRepository<T> where T : class
{
private static IRepository<T> Current
{
get
{
return UnitOfWork.Current.CreateRepository<T>();
}
}
public virtual IQuery<T> GetAll()
{
return Current.GetAll();
}
public virtual void Save(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
Current.Save(entity);
}
public virtual void Update(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
Current.Update(entity);
}
public virtual void Delete(T entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
Current.Delete(entity);
}
}
I'll get into the Unit of Work stuff in my next post.
In earlier posts I talked about about creating Domain Driven Design
style repositories using Linq to SQL. These allowed us to swap between
Linq to SQL repositories and In Memory ones easily (and really anything
that could support IQueryable<T>, this ensured some very nice
testabiliy. In this post I thought I'd go over some it again as well as
a some refactoring I had done to simplfy things, as well as how to
create simple Active Record style data access on top of our
repositories and therefore still ensuring our testability.
Our IUnitOfWork and its implementations (SqlUnitOfWork
and InMemoryUnitOfWork) haven't changed. However given that
IDataSource<T> and IRepository<T> are essentially the same
I decided to remove IDataSource<T>. Now that we have two
implentations of IRepository<T> (InMemoryRepository and
SqlRepository) we need one that uses these repositories and forms the
base class for our aggregate repositories.
This
base Repository<T> forms the foundation for it all, internally
it's only really a decorator around the actual specialised repository
that's accessed from the current Unit Of Work (more about this in a
later post).
public class Repository<T> : IRepository<T> where T : class
{
public static IRepository<T> Current
{
get
{
return UnitOfWork.Current.GetRepository<T>();
}
}
public Repository()
{
}
public IQueryable<T> GetAll()
{
return Current;
}
public virtual void Update(T entity)
{
Current.Update(entity);
}
public virtual void Update(IEnumerable<T> entities)
{
Current.Update(entities);
}
public virtual void Delete(T entity)
{
Current.Delete(entity);
}
public virtual void Delete(IEnumerable<T> entities)
{
Current.Delete(entities);
}
public virtual void Save(T entity)
{
Current.Save(entity);
}
public virtual void Save(IEnumerable<T> entities)
{
Current.Save(entities);
}
public IEnumerator<T> GetEnumerator()
{
return Current.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
Type IQueryable.ElementType
{
get { return Current.ElementType; }
}
Expression IQueryable.Expression
{
get { return Current.Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return Current.Provider; }
}
}
Active Record, this seems to be
the way a lot of people think data access should be, a few static
methods on your classes and away you go. From a testability point of
view I feel repositories certainly work better, but for smaller data
driven applications Active Record can certainly be the way to go.
I'd
like to support both camps with this system so lets build on top of
what we already have, first we'll need a static accessor to the current
repository, we can do that through the unit of work, but since we
already that in our base class we'll just expose that. Now anytime we
need our repository it can be accessed through
Repositor<T>.Current. This lets us built our ActiveRecordBase.
public abstract class ActiveRecordBase<T> where T : ActiveRecordBase<T>, IIdentifiable
{
public static IQueryable<T> GetAll()
{
return Repository<T>.Current;
}
public static T GetById(int id)
{
return GetAll().Where(i => i.Id == id).FirstOrDefault();
}
public static IQueryable<T> Find(Expression<Func<T, bool>> predicate)
{
return GetAll().Where(predicate);
}
public static void Save(T entity)
{
Repository<T>.Current.Save(entity);
}
public static void Update(T entity)
{
Repository<T>.Current.Update(entity);
}
public static void Delete(T entity)
{
Repository<T>.Current.Delete(entity);
}
}
One important item in there is the IIdentifiable interface, I've seen
some posts around either using Dynamic Linq or reflection to implement
the GetById method but I prefer this. This won't work for all objects
that dont't have an identity column, but for most of mine it's fine.
This allows us something really cool, a kinda mix in. A conditional extension method on the repository class.
public interface IIdentifiable
{
int Id
{
get;
}
}
public static T GetById<T>(this IRepository<T> repository, int id) where T : class, IIdentifiable
{
if(repository == null)
throw new ArgumentNullException("repository");
return repository.Where(i => i.Id == id).FirstOrDefault();
}
public partial class Product : ActiveRecordBase<Product>, IIdentifiable
{
public static IQueryable<Product> GetOnSaleProducts()
{
return GetAll().Where(p => p.IsOnSale);
}
}
Next post I'll set up a unit test base class for the in-memory tests and managing our unit of work.
So there's been a lot of commenting back and forth at the moment
concerning the new Microsoft Entity Framework and especially the "vote
of no confidence" by members of the Alt.Net and DDD communities. This I
can understand, the current EF certainly doesn't meet any of their
requirements for a toolset or framework.
The EF team looks to have taken some of this criticism on board and the Entity Framework Design blog gives some good indications we could end up with an excellent toolset.
The bastard step child in all of this is LINQ to SQL, certainly all the attention is on EF and as Ian Cooper
says "I would like to see a commitment from the Data Platform team to
stop
its focus on talking LINQ to SQL down as a RAD tool and tallking up its
advantages for use in the OO approaches to software development." I'd
like to see this as well. For small to medium projects this could an
excellent foundation, I'd love to see it opened up by the Data team,
the provider model for it is mostly there, hidden away under internals
and sealed classes.
On
a personal note, I'm still hunting for a product idea, my brain seems
to overly critical at the idea phase. I'm currently working on common
libraries for my work and I'll share some of the ideas that come out it
soon. I'd like to polish of the LINQ to SQL repositories and building
it into a business framework.
Since I wrote the earlier code in "Using LINQ to initialize DI Containers"
I've cleaned up the LINQ query to incorporate the assemblies loop and
also to use the First extension method to make things a bit more
readable.
var services = from a in assemblies
from t in Assembly.Load(a).GetTypes()
where t.GetInterfaces().Length > 0 && t.IsSubclassOf(typeof(ServiceBase))
let i = t.GetInterfaces().First()
where !Container.Kernel.HasComponent(i)
select new
{
Interface = i.IsGenericType ? i.GetGenericTypeDefinition() : i,
Component = t
};
foreach(var service in services)
{
Container.AddComponent(service.Interface.FullName, service.Interface, service.Component);
}