Linq Repositories, Lifetime Manaqement and Unity

A while back I posted about the MvcSupportFacility and alluded to a future post about abstracting away LinqToSql so that your application doesn’t need to be aware that it is talking to LinqToSql at all. Unfortunately due to me being lazy (hey I could make up a better excuse but I’m lazy) I never did get around to writing that post.

Timagehe basic premise is simple. I want to leverage LinqToSql in my application but I don’t want to take a dependency on it (that is, if I need to rip it out it’s not going to hurt too badly). What I need is some kind of abstraction over the top of the LinqToSql DataContext that I could easily implement using another technology. Enter the IRepository<TEntity>.

It’s a simple enough interface which enables you to think about warehouses of information in your application without really worrying about where they come from.

What I envisage is some kind of LinqToSqlRepository which implements the interface. For each class in our system which represents a table in the LinqToSql sense, there will be a repository for just that class. Although there will be many repositories they will all talk to the same Data Context.

Less chat more code right? What does a LinqToSql implementation of IRepository<TEntity> look like.

public class LinqToSqlRepository<TEntity> : IRepository<TEntity> 
where TEntity : class
{
private readonly Table<TEntity> table;

public LinqToSqlRepository(DataContext context)
{
table = context.GetTable<TEntity>();
}

#region IRepository<T> Members

public IQueryable<TEntity> All
{
get { return table; }
}

public IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> filter)
{
return table.Where(filter);
}

public void Add(TEntity newEntity)
{
table.InsertOnSubmit(newEntity);
}

public void DeleteWhere(Expression<Func<TEntity, bool>> filter)
{
table.DeleteAllOnSubmit(table.Where(filter));
}

public void Delete(TEntity entity)
{
table.DeleteOnSubmit(entity);
}

#endregion
}



Simple huh? Here’s a simple usage from an MVC application that I’m working on at the moment:



public ActionResult List(int page)
{
var allTitles = Titles
.All
.InPagesOf(5)
.Page(page);
return View(allTitles);
}


Now we just need: a) A way to control the lifetime of our DataContext (we want one per connection), b) A method of constructing an LinqToSqlRepository<TEntity> with the DataContext of the current request and c) a method of injecting our repository into the code that needs it.



Luckily for me I’m using a ControllerFactory which delegates out to the Unity Inversion of Control (IoC) Container so I can tackle all three fairly easily. During the Application Start event of my application I am initializing my container using the following code. I’ll explain bits of it as we go along:



container.RegisterType<DataContext, UgliDataContext>(new RequestContextLifeTimeManager(typeof(DataContext)));



What this code is doing is setting up a Type-Mapping so that when the code requests a DataContext object from the container it will get an instance of the UgliDataContext class. The UgliDataContext class is the one generated by the designer by dragging tables onto the designer surface. Nearly all it has in it are some helper-attributes which make it easier to work with directly. As these will change with every DataContext we create in all apps down the road we don’t want our repository to depend on them anyway.



One thing which the designer-generated DataContext does have which is useful to us is a constructor that takes zero parameters (it defaults to Attribute Mapping and the Connection String from the config file). There is a subtle problem here though in that there are multiple constructors and we want to ensure that Unity uses the zero-parameter one (by default it uses a sort of greedy algorithm). There is an InjectionConstructorAttribute that we could use to mark up the constructor we’d like it to run but as this is generated code it will erase it each time we regenerate. Here’s what we do instead:



container.Configure<InjectedMembers>()


         .ConfigureInjectionFor<UgliDataContext>(


                new InjectionConstructor()


          );



Looks a little funky. This code configures the InjectedMembers extension (of Unity) for the UgliDataContext class and tells it to use a constructor that matches the parameters of the InjectionConstructor constructor that we created, which in our case has zero parameters. Sweet. So now container.Resolve<DataContext>() is (very) roughly equivalent to new UgliDataContext(). Next chunk of code:



var assembly = Assembly.GetExecutingAssembly();


var types = assembly.GetTypes();





foreach (var type in types)


{


    if (type.IsAbstract)


        continue;





I hope that this is pretty straightforward. We are just looping over all of the types in the current assembly and skipping over the abstract ones. Once we have the non-abstract ones:



    var tableAttributes = type.GetCustomAttributes(typeof(TableAttribute), true);


    if (tableAttributes.Length > 0)


    {


        var serviceType = typeof(IRepository<>).MakeGenericType(type);


        var concreteType = typeof(LinqToSqlRepository<>).MakeGenericType(type);





        container.RegisterType(serviceType, concreteType, new RequestContextLifeTimeManager(serviceType));


        continue;


    }



Here we are checking to see if the type has a TableAttribute on it. This attribute is added by the LinqToSql Designer to the generated classes for you and the Data Context (with the AttributeMapping) uses it to control which objects it can deal with and how. If it has this attribute we register another type mapping into the container so that if a client requests IRepository<T> they get a LinqToSqlRepository<T>.



There’s a few other bits in this register methods (it auto-registers controllers and services too) which aren’t really that relevant to the discussion at hand. So apart from the constructor configuration section, much of the above is Reflection-fu. The only other pieces are the calls to container.RegisterType which takes 3 parameters. The first one is a type that the client requests. The second one is the type the container will build up and return. The last one is a Lifetime Manager.



A Lifetime Manager in Unity parlance is an object which is responsible for how and when an instance is created by the container. Out of the box Unity has a few Lifetime Managers:




  • TransientLifetimeManager – Literally does nothing. The net effect is that each time you ask for an object you get a new one


  • ContainerControlledLifetimeManager – Keeps a reference to it’s instance once created until the container is disposed of. If the instance is disposable it is also disposed when the container is. The upshot is that the instance is a singleton for the lifetime of the container.


  • ExternallyControlledLifetimeManager – Keeps a WeakReference to the instance.



So where is RequestContextLifetimeManager? I created it. Creating a new LifetimeManager is actually quite simple. Here it is:



public class RequestContextLifeTimeManager : LifetimeManager
{
private readonly Type type;

public RequestContextLifeTimeManager(Type type)
{
this.type = type;
}

public override object GetValue()
{
return HttpContext.Current.Items[type.FullName];
}

public override void RemoveValue()
{
HttpContext.Current.Items.Remove(type.FullName);
}

public override void SetValue(object newValue)
{
HttpContext.Current.Items[type.FullName] = newValue;
}
}



So what is going on here? The RequestContextLifetimeManager is initialized with a type which it’s going to use as a key in a dictionary (via the FullName property). When client asks for our type, the GetValue method is called.



The first time it is called GetValue will return null (as there’s nothing in the context items dictionary under that key). As GetValue returns null the container will go and do it’s thing and create our instance for us. Just before it returns the instance to the client (calling code) it will call SetValue on the LifetimeManager.



When SetValue is called it will store the instance into the Context dictionary. Then when something else requests the same type (calls GetValue again) it will get the one already created. Because of the way that the HttpContext works, the dictionary will get re-created for each request and is unique to that request.



So there you have it. It took a little explaining but that is a (relatively) simple architecture for abstracting away LinqToSql from the rest of the application using Unity. Although the sample is for ASP.NET MVC it would work equally well in WebForms. If you wanted to go beyond the web the repository stuff would still work but you’d need to do something else for Lifetime Management.



image There is one piece which is missing from the above and it’s going to frustrate people unless they are aware of it. Nowhere in the above code is there a call to SubmitChanges on our DataContext. This means that no matter what you do, currently nothing will ever be saved to the database. I didn’t want to put a SubmitChanges method on the IRepository because of the way LinqToSql works you’d end up with a call to IRepository<Titles>.SubmitChanges saving the changes to all other repositories. I thought this was misleading at best and dangerous at worst.



Instead I have an interface called ICheckPoint which contains a Save method. This gives me control over the process without being misleading. There is, of course, a corresponding LinqToSqlCheckpoint implementation as well.



Thoughts? Questions? Like puppies? Please leave a comment and tell me.

unitylinq-to-sqlasp-net
Posted by: Mike Minutillo
Last revised: 27 May, 2011 02:42 PM History

Comments

19 Jan, 2010 02:36 AM @ version 0

Thanks for this post man! I have been thinking about the behaviour of unity in web environments and this has opened my mind!!

24 Feb, 2009 12:53 PM @ version 0

I had to modify your auto registration of repository types a bit, since my DataContext do not live in the same assembly as my website, here is the code that fixed that issue:

var assemblies = AppDomain.CurrentDomain.GetAssemblies();
var repositoryAssembly =
assemblies.Single(x => x.FullName != null && x.FullName.Equals("Repository, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
var types = repositoryAssembly.GetTypes();

....
the rest is the same

26 Jan, 2009 12:46 AM @ version 0

Thanks for this post, I've been working with Unity for the first time and I needed an example of a lifetime manager that was tied to a http request. And this post was just that, thanks!

29 Oct, 2008 03:03 PM @ version 0

I promised I'd read this. I did. Now my head hurts. :)

No new comments are allowed on this post.