In my past few posts (here and here) I've been looking into how to use Dapper. I've looked at how basic CRUD operations are performed and looked at some of the extensions available out there to help. I've also shown that Dapper is used out in the wild with sites such as Stackoverflow, but how easy is it to implement Dapper into an existing project replacing an existing ORM? In this post I will show you how easy it is to replace an Entity Framework implementation with Dapper.
The existing solution I will be modifying will be Nerd Dinner site.
Why Nerd Dinner?
The reason why I've chosen Nerd Dinner is that it is a full working website with source code available. It is more than the general "Hello World" web site examples as it uses a number of different libraries to expand on the exiting MVC framework. Also it performs a number of different types of database queries that should test to see how flexible Dapper really is. Using an existing solution rather that starting one from scratch will show how easy or hard it is to retrofit Dapper into a solution. Also using Nerd Dinner will give a new solution a base for comparison against, whether it will be for example speed, lines of code or some other metric.
This version will not be the fastest or most efficient implementation of Dapper, this will be for later parts in the series, but it will focus on simply replacing the existing Entity Framework queries with Dapper. I will show how you can leave the majority of your code which is outside the data access layer unchanged, while changing your data provider.
As the Nerd Dinner solution uses the repository pattern all that is required is to create a new implementation of the
IDinnerRepository interface. Providing that my implementation of the interfaces returns the same results as the Entity Framework version, then the end user should notice no difference in the data shown on the site. If the Nerd Dinner solution used dependancy injection such as Ninject then all we would need to do to use the new Dapper repository would be to change the mapping. However as it doesn't use dependancy injection, we need to change all references of
DapperDinnerRepository. The full code listing of the new repository can be found here.
To return a single Dinner I used the multiple results feature of Dapper. That way I can return both the Dinner and the list of RSVP's in one query rather than using multiple queries.
List of Dinners
The code below shows how I implement returning a list of Dinners. As some of the controller actions require the count or list of RSVPs, I also return the RSVPs associated with each Dinner. This is not the most efficient way of doing this, as some controller actions won't even be using the RSVPs, so this is making excessive calls to the database. Also each Dinner is making the same call to the database to return the RSVPs; again this is excessive and there are more efficient ways. In a future part of this series I will show how we can improve the efficiency.
Insert and Updating Dinners
The good thing about Entity Framework is that it "tracks" changes made to objects, so when
SaveChanges() is called it "knows" if an object is changed, unchanged or new, and performs the relevant operation, i.e. insert, update or none. However without changing the underlying code for the objects themselves, there is no way we can determine if an object has changed. We can determine if it is new because it will have an "Id" of zero (the default value). Therefore a rough solution would be to do an insert when the "Id' is zero when we come to insert or update objects. Otherwise, we just perform an update whether the object has changed or not. In a future blog I will demonstrate a more efficient way of doing inserts and updates.
As you can see, provided the architecture of your system is in place, it is easy to quickly change the data access layer.
The code for this example is available of GitHub here, feel free to fork the code and improve, change or correct any of it.
In the next part of the series, I will be showing that if you refactor other parts of the solution, and in the case of Nerd Dinner the controllers, then we can fully leverage the power of Dapper. We will hopefully be able to see the benefits of using Dapper over Entity Framework and the flexibility it gives.