Developers choose Entity framework ORM (EF) for better productivity when accessing the database. But, when the product is built that went from bare bones to very complex and heavy data access then comes the performance.
Sometimes its the Entity framework that kills the performance so the choice when searching for a better ORM than Entity framework is Dapper.
In this post, I’ll walk you through how we can replace the existing entity framework code with dapper.
Entity models and accessing data with Entity framework
Here are our entity model classes for a simple Todo application.
public class ToDoItem { public ToDoItem() { Details = new HashSet<ToDoItemDetails>(); } [Key] public int Id { get; set; } public string ToDoText { get; set; } public bool IsCompleted { get; set; } public int Priority { get; set; } public ICollection<ToDoItemDetails> Details { get; set; } } public class ToDoItemDetails { [Key] public int Id { get; set; } public int TodoItemId { get; set; } public string Notes { get; set; } public DateTime CreatedDate { get; set; } public ToDoItem TodoItem { get; set; } }
And here is our method to retrieve all todo items and its details using entity framework.
public IEnumerable GetAll() { return _context.TodoItem.Include(a => a.Details).ToList(); }
The above code looks so minimal and maintainable. Let’s see how the same thing can be done with Dapper.
Accessing data with Dapper
For the purpose of the article, I’m making use of the entity models that are created for entity framework. In real time, we’d have to use the DTO or a simple view model to return the data from the repository.
//accessing with Dapper
public IDbConnection Connection { get { return new SqlConnection(_configuration.GetConnectionString(“MyConnectionString”)); } } public IEnumerable GetAll() { var todoDictionary = new Dictionary<int, ToDoItem>(); string query = “SELECT * FROM ToDoItems td JOIN TodoItemDetails details ON details.TodoItemId = td.Id”; using (IDbConnection con = Connection) { var result = con.Query<ToDoItem, ToDoItemDetails, ToDoItem>(query, (todoItem, todoItemDetail) => { ToDoItem todoEntry; if(!todoDictionary.TryGetValue(todoItem.Id, out todoEntry)) { todoEntry = todoItem; todoEntry.Details = new List(); todoDictionary.Add(todoEntry.Id, todoEntry); } todoEntry.Details.Add(todoItemDetail); return todoEntry; }); return result; } }
The above code is a bit complex as we are dealing with multiple tables and we have to fill the details list object in the TodoItem class.
As you can see we have more work to do with Dapper. But, there isn’t anything special except that it looks like the ADO.NET style of having the query into a string and supplying arguments to the Query method to get the appropriate result which can be mapped to ToDoItem class.
Design considerations
When modifying applications like the above one, it’s better to have an interface like repositories and when you implement these repositories you do it separately for entity framework access and separate for Dapper.
I recommend implementing a repository interface in a separate class for a specific ORM.
We already have EF in the repository implementation. If we want to have a method specific implementation as in our example GetAll() method is replaced with the existing EF code. Instead, it’s better to have a separate class for Dapper implementations. When you want to have the dapper implementation, call the dapper specific method in that class.
Conclusion
As you can see we have removed the existing entity framework code with Dapper code for better performance. I have other methods in the repository that make use of entity framework for reading and writing to the database.
Writing code in LINQ to SQL is more productive than writing in Dapper. But, when it comes to performance dapper wins over entity framework.
We can have both LINQ to SQL and entity framework code in the same class to access the database. But, this is not a good design consideration as we may be switching to a better performing ORM tomorrow.
Karthik is a passionate Full Stack developer working primarily on .NET Core, microservices, distributed systems, VUE and JavaScript. He also loves NBA basketball so you might find some NBA examples in his posts and he owns this blog.