{ independency injection }

In my last article, I showed you a way of creating an interface for the LinqToSql DataContext so that you can mock the actual implementation for unit testing. Well, there is another benifit to creating such an interface. The interface we created, uses LinqToSql's underying generic methods. Using this, we can create a completely generic repository class, to handle all data transactions from our data-layer.

I won't get into the Repository Pattern or Domain Driven Design, because there are too many people out there, WAY smarter than me discussing it in full. I use this pattern mainly for convenience in testing and reducing code, but it is worth reading up on -- it is some great stuff!

First off, there are literally a THOUSAND articles out there talking about the Repository Pattern and quite a few articles discussing implementing this with the LinqToSql DataContext. None of them were quite what I needed, so I present to you, my version with ideas borrowed from this article and this one (both of these concepts are awesome, however they lacked the IDataContext piece so that it can be unit tested.

IDataContext

First, let's assume that you have already followed my last article, and your DataContext implements IDataContext.

This class uses Dependency Injection and accesses the DataContext as IDataContext. This allows us to create unit tests for this class with a mocked data-context.

There are two Get methods, both of which pass a Where expression down to the Linq extensions. The first attempts to build an expression manually. This is assuming that you use int as your IDs. If you don't you can always update the code to fit your needs. GetPrimaryKey() is an extension method written by the genius, Mike Hadlow over here. It's awesome, and I included it down below.

Both return a single instance from the DataContext, but the Get(Expression<Func<T,bool>> selector) function allows a more complex lookup (for complex identities or whatever). It's passed as an expression, just like the "Where()" function, in the Linq extensions.

Sample Usage

So what does this buy us? Well, with this simple generic class we suddenly have a full, strongly-typed repository layer for each object in the DataContext.

// You can now declare and use "specific" repositories for your Linq objects.

_UserRepository = userRepository;

_CarRepository = carRepository;

}

publicvoid DoSomething()

{

// Basic get by ID

var car = _CarRepository.Get(1);

// Complex selector

var differentCar = _CarRepository.Get(c => c.Name == "Ford");

// Basic list

var listOfUsers = _UserRepository.List();

// List, with filters

var filteredUsers = _UserRepository.List()

.Where(u => u.Name.StartsWith("T"));

// Add

_UserRepository.Add(newUser { Name = "Fred"});

_UserRepository.SubmitChanges();

// Update

var editableUser = _UserRepository.Get(1);

editableUser.Name = "New Name";

_UserRepository.SubmitChanges();

}

}

Obviously, you can only create a Repository<T> for a class in your context. Otherwise, you would see an epic exception.

Another great thing about this pattern is it's benifits with code-coverage. You can create unit tests for each of these methods and in effect cover your entire data-layer. Not to mention the value in having less code laying around.