New Github and Nuget Package: Division42.Data.Repository.EntityFramework

OK, this is it! If you are a developer and have talked to me about a relational database in the past year or two, you no doubt have heard my long-winded speeches on how I like the “Repository Pattern” on top of Entity Framework.

For how amazing and fantastic Entity Framework is, it’s not based off any interfaces. The underlying DbContext class MUST connect to an actual database to work. So, if you want to properly unit test any of your code that uses EF, you can’t. I have no idea why in the year 2016 this component was written this way, but it is.

My Solution:
My solution has been to create a repository interface which allows for simple CRUD operations. Any code which requires these repositories can just point to the repository interface, and in the constructor, you can pass in whichever implementation you want. This is the best of all worlds. For production use, you use Entity Framework. For unit testing, you pass in an in-memory repository.

The tricky thing, and the part that has changed slightly over several months is the abstract EF implementation of this interface. I have built, re-built, and refactored this several times and have finally got it dialed-in. So, I made a Nuget package and put the source on Github.

Wait, what is the problem you are trying to solve?
Yes, if you’ve heard my long-winded speech on this topic, it’s often not clear on what the problem is. The issue is that you don’t start running into the limitations of EF until you are neck-deep. So, let’s start with some obvious usage of Entity Framework. Assume you had code like this, directly in your application:

public IEnumerable<Customer> GetCustomerStuff()

{

    using (PointOfSaleContext context = new PointOfSaleContext())

    {

        return context.Customers.Where(item => item.LastName == “Doe”);

    }

}

OK, so you connect to a database and get some data. How do you unit test this method? Well, if you call it the way it is, it’s going to go to the database. This requires that the person (or build workstation) running the unit tests have access and connectivity to the database server. That’s not OK. Even if it was, that would mean that unit tests would constantly be adding/updating/deleting data. That’s a mess, and it’s not OK. Unit testing should be possible without connecting to anything external.

The next thing you might do is think that you can inject in the DbContext (that PointOfSaleContext) in the constructor, and potentially pass in some analog, some other in-memory representation of DbContex. But look at the definition of DbContext:

image

it’s not based off of any core IDbContext interface, in the year 2016, for some reason.

So, you think: I’ll just inherit from DbContext but not point to a database! The problem with that is the contructor itself attempts to connect to the database that you passed in, and any DbSet<T>’s that you set up, are also hard-wired to that same database.

Next you might think that you could use a mocking framework like Moq or RhinoMocks – but those also can’t mock around this because every aspect of DbContext expects there to be a real database connection there. So then you look at Microsoft.Fakes – and same issue, you simply cannot mock around.

The result: you absolutely, positively, without-a-doubt, cannot mock around or abstract-away DbContext.

This in itself, is frustrating, because this is a relatively new component and we, as an industry KNOW better. The answer is so simple, have DbContext implement an IDbContext and have DbSet implement IDbSet. If that were the case, we’d be done and this would be a non-issue. However, back in the real world…

This is why the Repository Pattern is attractive. This gives you database-agnostic access to entities in an underlying data store. It could be a database or it could be an in-memory model.

What are the projects?
Well, the first part I released a while ago, but I recently made a breaking change. Division42.Data is a Portable Class Library which simply defines a core IRepository. Since it is a PCL, it can be used from many different project types including UWP and Xamarin projects. The breaking change was that I removed the SQLite functionality. If needed, I will build out another Nuget package, just for that – or, you could! Feel free to fork the project or simply create your own Nuget package.

So, I versioned Division42.Data as 2.0.0, and re-published that as a Nuget package.

The big thing, and the new thing, is the Entity Framework implementation. This is a different Github project and different Nuget package. This has a dependency on this Division42.Data and the latest version of Entity Framework 6.x. This one is called: Division42.Data.Repository.EntityFramework. It is so-called because that is the namespace, and that is to which this functionality applies. More on the details in a minute. Here is where you can view the source or Nuget packages:

Github:

Nuget:

How does it work?
Ok, the biggest thing and the starting place is this base interface IEntityFrameworkRepository in Division42.Data.Repository.EntityFramework. This implements IRepository from Division42.Data, but adds some Entity Framework specific things. Now, these are not willy-nilly things, this is what I’ve been honing over several projects, for several months. This interface, I feel, covers everything that you need to use the Repository Pattern over Entity Framework. For example…

  • There is a “Context” property getter. This is assigned in the constructor of a class who implements this interface. This means that if you must, you will have direct access to the underlying DbContext object. Note though that this will likely make that specific piece of code not unit-testable, but understandably, sometimes you need to break the rules.
  • There is an “Entities” property getter. This too is assigned in the constructor of a class who implements this interface. Again, it you need direct access to the DbSet<T> of the entity on which the repository is operating, you have simple access to it. Care should be taken though, because DbSet<T> is also not mockable, so any code which uses this will likely not be unit-testable.
  • new “params” overloads for GetAll, GetByFilter, and GetById. These allow you to pass in an Entity Framework DbSet<T>.Include(“NavigationPropertyHere”) statements, to explicitly include sub-elements, or navigation properties of what is bring returned. Having this on a per-call basis is critical for application performance.

Having the ability to fine-tune exactly which .Include(..) statements to include on a per-call basis, that is key. I found that “Oh, I’d probably always want to include these sub-tables” didn’t work well when I JUST needed a fast, simple list for a Web API call. Having fine-grained control over exactly what gets returned was the final piece of this, for me.

How do I use it?
Well, that’s the easy part! The whole idea here was to make this ridicuously simple to use. In fact, for unit testing this in the Github project, I created an empty LocalDb database which shows all of this in action. So, assume you have a models like Customer –> Order –> OrderDetails like here. You might set up a DbContext like this. Where this stuff comes in is creating a repository on top of that DbContext. For that, take a look at CustomerRepository.cs – which looks like this:

public class CustomerRepository : EntityFrameworkRepositoryBase<Customer>

{

    public CustomerRepository() : this(new PointOfSaleContext())

    {

           

    }

    public CustomerRepository(DbContext context) : base(context)

    {

    }

 

    public override Customer GetById(Guid id, params String[] entityIncludes)

    {

        CheckIfDisposed();

 

        if (entityIncludes == null)

            throw new ArgumentNullException(nameof(entityIncludes));

 

        DbQuery<Customer> query = Entities;

 

        foreach (String entityInclude in entityIncludes)

        {

            query = query.Include(entityInclude);

        }

 

        return query.FirstOrDefault(item => item.CustomerId == id);

    }

}

The constructor of the abstract base class requires that you pass it in a valid DbContext. The only other thing you need to provide is a GetById(..). Why? Well, in short because in the abstract base implementation, almost everything is identical for getting, inserting, updating, etc – but, we don’t know what the name of your primary key is. In the future, if I can solve this in a more elegant way, I will. But until then, this is small piece of code which you must provide when inheriting from this class. If you implement just this one small thing, the abstract base class can do the other 99% of the heavy lifting.

So why do this, what does that buy me?

Ok, so with that little bit of code, you now have all sorts of functionality over that entity, for example:

image

So you have the original functionality of the IRepository in Division42.Data, but also the EF-specific stuff, already all wired –up!

customerRepository.GetByFilter(item => item.LastName == “Doe”,

    “Orders”, “Orders.OrderDetail”);

Something like this not only gets data, but let’s you specify the levels of navigation properties to include!

Bottom Line:
For me, I’ve been using this approach for probably close to 2 years now. Every time I take on a project, i would whip up something very similar and make small tweaks here and there. However, with two recent projects, I feel confident that this is a really good starting point. Meaning, from here on out, when I am using a relational database, I’m going to use this Nuget package and evolve it, as necessary.

Meanwhile, if you want a simple way to access your data, and want your code to be unit testable, it’s available for use on Nuget – just add a reference to Division42.Repository.EntityFramework and it will add the Division42.Data and Entity Framework dependencies.

Or, if you want to contribute or take this in a different direction – please fork the project on Github.

Posted in Best-practices, Computers and Internet, Development Tools, DI and IOC, Entity Framework, General, New Technology, Open Source, Organization will set you free, Professional Development, Uncategorized, Unit Testing
2 comments on “New Github and Nuget Package: Division42.Data.Repository.EntityFramework
  1. Muni says:

    Rob, great. You are absolutely correct. Not able to cover all the aspects using Rhino mock. So I will choose to create instance of the DbContext for the test. If we have a piece of code for unit testing, will be good for the perfect understanding.

    Just a request!

    Like

    • Robert Seder says:

      Muni,

      Good point. Well, the idea would be that in Web API for example, a controller wouldn’t use a DbContext directly – it would use a repository, and you would defer it out as far as possible. I use a concept like this: https://gist.github.com/RobSeder/1bc2609c3569951f815f

      The idea being that by the time you are inside of the Web API controller (CustomerController.cs), you are working with an IRepository which – at run-time is populated with a DbContext-based implementation. However, for unit testing, you could pass in an in-memory repository, and FULLY test the whole Web API class – because everything is written to work with the interface.

      Does that help? Any questions??

      -Rob

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 2 other followers

%d bloggers like this: