Wednesday, February 25, 2009

Entity Framework: Abstracting ObjectContext

Wither you are a TDD purest or not, if you are developing with Entity Framework and testability is important to you, then you have tried some workaround or applied some pattern to make testing possible in your project. When you have a class or method which depends on any external resource it is important to create some sort of abstraction in order to remove a dependency upon that resource so you can effectively test your code.

The client I am currently working for has chosen to create a repository class which takes an ObjectContext argument in the constructor. The repository implements a custom interface and that interface is used to reference the repository where needed.

While this meets our needs I was late to the game when I was brought on, so when I suggested an alternative I was praised for my suggestion but because there was already an implementation we ultimately stuck with what we already had. So I decided just to make a quick post describing my own solution and touching on what I see as the benefits.

I (heart) Partial Classes

My ideal framework is open, extensible and makes abundant use of public interfaces which allow me to hook in where I need to so I can get the job done. The team I would say has done the best job of this would be the ASP.NET MVC team. I’m a bit picky about my ORM solutions and I just don’t feel like LINQ2SQL and Entity Framework have quite done everything the way I like. And the ability to extend or change the behavior of Entity Framework seems to be pretty lacking. But there is one thing that I have found to be invaluable as I have worked with these two ORM frameworks – Partial Classes.

Open any *.designer.cs file generated by either LINQ2SQL or Entity Framework and you will see an abundant use of the C# keyword “partial”. While it doesn’t allow me to modify existing Entity Framework behavior I can certainly add to it.

Partial classes are what make it possible for me to simply and elegantly create an abstraction of my ObjectContext without bending over backwards.

The Abstraction

So as an example, I have an AdventureWorks database and I want to abstract the associated ObjectContext created by my edmx designer. To simplify things I’ll simply referece the Person and Address tables. So after finishing with my edmx file, dragging Person and Address to the designer surface I’ll create an interface which looks like this:

publicinterface ICustomRepository : IDisposable

{

IQueryable<Person> People { get; }

IQueryable<Address> Addresses { get; }

Int32 SaveChanges();

void Detach(Object entity);

void Attach(IEntityWithKey entity);

void DeleteObject(Object entity);

void AddObject(String entitySetName, Object entity);

}

Because of the difficulty of implementing ObjectQuery<T>, I like to expose the entity set properties on my ObjectContext as IQueryable<T>. In most cases this is sufficient, where it isn’t I can check to see if the IQueryable is of type ObjectQuery. If not then I know I’m in a testing scenario and I can safely skip what I was about to do. Here’s an example of an extension method I’ve created which allows me to use eager loading on my IQuerable interface.

Once I’ve added a read-only (property get) for each entity set in my context, then I include the signature for each ObjectContext method I will be using in my application. If I need additional ones down the road, all I need to do is add the signature to the interface and I’m off and running. So I’ve included SaveChanges, Detach, Attach, DeleteObject and AddObject. Feel free to include others you need they’re free and you don’t need to provide any implementation.

The Implementation

Now that we have an interface that can be used throughout our application in place of our ObjectContext, how do we use it to remove our dependency on ObjectContext? Let’s say for argument’s sake our ObjectContext is named AdventureWorksModel. Then we would add a class file to our project which contains our edmx file and in that class file we would define a new class like this:

publicpartialclass AdventureWorksModel : ICustomRepository

{

IQueryable<Person> ICustomRepository.People

{

get

{

returnthis.People;

}

}

IQueryable<Address> ICustomRepository.Addresses

{

get

{

returnthis.Addresses;

}

}

}

First, notice the property names (ex. ICustomRepository.People). Because the properties exposed by the designer generated class are of the type ObjectQuery we have to provide an “explicit implementation” of our interface for those properties. No casting is required, but the compiler and the runtime are looking for properties of type IQueryable and so unless you include the name of the interface in the property name it won’t compile. But because ObjectQuery implements IQueryable, that’s all you have to do. Now you can reference ICustomRepository anywhere and you’re good to go.

Usage

There are any number of ways you can provide access to your repository. The easiest, in my view is using an IoC container like Unity or Spring. Here’s an example of using Unity to register your ObjectContext and resolving it from your container:

Once you’ve registered your ObjectContext in the container your application can get a reference to it anywhere through the custom interface. Everything remains testable and there’s no need for any awkward machinations to use it.

Mocking the Abstraction

Now when you’re testing you can write your own mock objects or use your favorite mocking framework (I really like MOQ) to provide an implementation of your interface that isn’t dependent upon your database.

[TestClass]

publicclass DependentObjectTest

{

ICustomRepository _repository;

[TestInitialize]

publicvoid Init()

{

List<Person> people = new List<Person>();

List<Address> addresses = new List<Address>();

Moq.Mock mock = new Mock<ICustomRepository>();

mock.ExpectGet(r => r.People).Returns(people);

mock.ExpectGet(r => r.Addresses).Returns(addresses);

mock.Expect(r => r.AddObject("People", It.IsAny<Object>()))

.Callback<string, Person>((s, p) => people.Add(p));

mock.Expect(r => r.AddObject("Addresses", It.IsAny<Object>()))

.Callback<string, Person>((s, a) => addresses.Add(a));

_repository = mock.Object;

}

[TestMethod]

publicvoid Test1()

{

Person p = new Person();

_repository.AddObject("People", p);

Assert.AreEqual<int>(1, _repository.People.Count);

}

}

While this isn’t a realistic test scenario because it is only testing the mock object, it should give you an idea of how to mock up an implementation of the interface for use in a test scenario.

If you’re using Unity or something like it then in your TestInitialize method you’ll just change the last line to this:

Container.Register<ICustomRepository, AdventureWorksModel>();

Then your test method won’t need to reference it since the methods you’re testing will get the reference via the Container object.

Conclusion

Thus far, I have found this is a simple and elegant solution which works just like using ObjectContext in any scenario.