I've started work on a new project recently and the first thing for me to sort out is the Data Access Layer. Because the Repository pattern served me so well in the past, I'm going to start there.
However, the previous solution used a bespoke QueryBuilder which converted an ICriteria into the appropriate SQL. This SQL was then just passed through as CommandText on an ADO.NET connection to the appropriate database, Oracle or SQL Server.
What we did was to mock the Repository using LINQ to Objects, and this allowed us to construct our application in a Domain-Driven fashion.
Great!
However, there was always room for improvement. I've wanted to use LINQ as my ORM for quite some time now, and I know the purists out there will say that LINQ isn't an ORM, but for practical purposes in this project it's going to be.
Also, I've decided to use L2S rather than the Entity Framework. My mantra is Design For Test, and right now L2E is just not persistent-ignorant in the slightest. There are hacks as I've outlined in previous blog posts, but building hacks into the foundation of your application is a recipe for disaster.
While L2S may not be supported in future by MS, who cares?! It works, plenty of good, solid apps have been built on it, AND IF WE GET THINGS RIGHT, there's no reason why we can't switch to L2E v2.0 next year.
We can do this because we are going to abstract out the actual DataContext, and access our data using POCO and Repository pattern.
In addition, if we can swap out the DataContext, then given that LINQ to Objects and LINQ to SQL queries are the same (or at least I hope they are, more on this later) then we can have a set of queries that we can run on both in-memory and database sources. Truly Datasource-Agnostic.
I got the inspiration for this from
http://compiledexperience.com/Blog/post/Domain-Driven-Design-Repositories-in-LINQ-to-SQL.aspx - and it works!

This diagram shows the LinqToSQL assembly, but we can also replace the SQLDataSource and SQLUnitOfWork with a MemoryDataSource and MemoryUnitOfWork.
For example, if we want to test an in-memory collection, we do the following:
MemoryUnitOfWork context = new MemoryUnitOfWork();
Repository<Customer> r = new Repository<Customer>(context);
r.Save(new Customer(1, "Joe Bloggs"));
r.Save(new Customer(2, "Joanna Bloggs"));
IEnumerable<Customer> customers = from c in r.Fetch(null) where c.ID == 1 select c;
List<Customer> results = customers.ToList<Customer>();
Assert.AreEqual("Joe Bloggs", results[0].Name);And if we want to test an actual connection to a database using L2S:
DataContext db = new DataContext("Data Source=(local);Initial Catalog=DMGTest;Integrated Security=SSPI");
SqlUnitOfWork context = new SqlUnitOfWork(db);
Repository<Customer> r = new Repository<Customer>(context);
IEnumerable<Customer> customers = from c in r.Fetch(null) where c.ID == 1 select c;
List<Customer> results = customers.ToList<Customer>();
Assert.AreEqual("Joe Bloggs", results[0].Name);Note the line
IEnumerable<Customer> customers = from c in r.Fetch(null) where c.ID == 1 select c;
which is identical in both versions.
My next step is to encapsulate the queries using the Specification pattern,
as Ritesh shows here.
So now we have completely isolated our domain from our DAL, and with the introduction of the Specification pattern we can look at our queries from a domain perspective also.
The code is just bashed out at the moment, but if you want it then just drop me a line and I'll send it over.
