0% found this document useful (0 votes)
182 views

Using Dapper Asynchronously in

Using Dapper (micro ORM) Asynchronously in ASP.NET Core 2.1

Uploaded by

Giovani Brondani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
182 views

Using Dapper Asynchronously in

Using Dapper (micro ORM) Asynchronously in ASP.NET Core 2.1

Uploaded by

Giovani Brondani
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 1

Using Dapper Asynchronously in

Exception Not ASP.NET Core 2.1


Found  A YEAR AGO  DAPPER · ASP.NET-CORE · SAMPLE-PROJECT · TUTORIALS

Stories from a web developer

CATEGORIES
My team is nally embarking on a new project that we can use
ABOUT ME
ASP.NET Core for. I've also been waiting a long time to use the
SPEAKING ENGAGEMENTS "micro-ORM" Dapper in one of our projects, and this new one ts
the bill: we need incredible performance and minimal coding.
Recent Posts
The Repository-Service Pattern with DI
and ASP.NET Core So what happens when the winds of change meet the waves of hope? You get
Joining the Dark (Mode) Side
mixed-up nautical imagery! And, hopefully, some insight into ASP.NET Core.
Bucket Sort - The Sorting Algorithm
Family Reunion
In this post, we're going to create a very simple ASP.NET Core 2.1 application
Radix Sort - The Sorting Algorithm
Family Reunion which uses Dapper to access data. There's already a sample project worked up
Gnome Sort - The Sorting Algorithm over on GitHub, and you might want to use that to follow along here.
Family Reunion

Featured Posts With all of that said, let's climb aboard the tutorial Titanic!
The Repository-Service Pattern with DI
and ASP.NET Core

Introducing The Sorting Algorithm


Family Reunion

Be The Laziest Programmer You Can Be

Patience, Outrage Culture, and Mr.


Berger's Class

The Most Powerful Question: 4 Rules to


Help Developers Ask "Why?"

Keep in Touch!
 Twitter

 GitHub

 Subscribe via RSS

 Subscribe via email Hmmmm. Maybe that wasn't the best metaphor.

Buy me a coffee Step 1: Get the NuGet Package


© Matthew Jones 2019 First things rst, we need to grab the NuGet package for Dapper. In Visual Studio,
Ghost & StayPuft
you can do this by right-clicking on your project le and selecting Manage NuGet
Packages and then search for the Dapper package, like so:

With that installed, let's try creating a repository.

Step 2: Creating an Employee Class and


Repository
For this demo, I am not going to go over how to create a database or show a
demo database with sample data; I don't have one available and it's a pain to
make one. So let's assume we have a table Employee with columns for FirstName,
LastName, ID, and DateOfBirth. We can make a corresponding C# class for this
table, like so:

public class Employee


{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}

Now we need a sample repository. Let's call it EmployeeRepository and give it an


interface so we can use ASP.NET Core's Dependency Injection setup.

Here's the interface:

public interface IEmployeeRepository


{
Task<Employee> GetByID(int id);
Task<List<Employee>> GetByDateOfBirth(DateTime dateOfBirth);
}

Since this is an async implementation, note the use of the Task<> class (and refer
to an earlier article of mine for a refresher on how async and await keywords
work in ASP.NET.

Now we can work up a skeleton implementation of this repository. Here's what


we're starting with:

public class EmployeeRepository : IEmployeeRepository


{
public async Task<Employee> GetByID(int id)
{

public async Task<List<Employee>> GetByDateOfBirth(DateTime dateOfBirth)


{

}
}

We also need to update our project's Startup le to include our new repository in
the services layer:

public class Startup


{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)


{
services.AddTransient<IEmployeeRepository, EmployeeRepository>();

services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)


{
//...
}
}

Next, we need to enable this repository to use Dapper. Before we can do that,
however, we need it to be aware of what connection string we are using.

Step 3: Injecting IConfiguration


Very often in ASP.NET Core projects, Connection Strings are de ned in the
appSettings.json le:

{
"Logging": {
"LogLevel": {
"Default": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"ConnectionStrings": {
"MyConnectionString": "MyConnectionString"
}
}

The problem is: how do we pass that connection string to the repository so it can
create a SqlConnection object for Dapper to use?

ASP.NET Core introduces a new IConfiguration object which can be injected into
other classes. That injected instance will contain a method called
GetConnectionString which we can use to obtain our connection string from the
appSettings.json les. So, let's inject IConfiguration like so:

public class EmployeeRepository : IEmployeeRepository


{
private readonly IConfiguration _config;

public EmployeeRepository(IConfiguration config)


{
_config = config;
}

//Remainder of file is unchanged


}

Step 4: Creating a SqlConnection


With the injected IConfiguration now available to our repository, we can create a
Dapper-enabled SqlConnection object that all of our repository's methods can
utilize.

public class EmployeeRepository : IEmployeeRepository


{
private readonly IConfiguration _config;

public EmployeeRepository(IConfiguration config)


{
_config = config;
}

public IDbConnection Connection


{
get
{
return new SqlConnection(_config.GetConnectionString("MyConnectionString"
}
}

//Remainder of file is unchanged


}

Step 5: Employee by ID
Let's rst create a method to return employees by their ID.

To start, let's remember that the way Dapper works is by processing raw SQL and
then mapping it to an object. Because our table columns and object properties
share the same names, we don't need to do any special mapping here.

Here's the implementation of our GetByID method:

public class EmployeeRepository : IEmployeeRepository


{
//...

public async Task<Employee> GetByID(int id)


{
using (IDbConnection conn = Connection)
{
string sQuery = "SELECT ID, FirstName, LastName, DateOfBirth FROM Employe
conn.Open();
var result = await conn.QueryAsync<Employee>(sQuery, new { ID = id });
return result.FirstOrDefault();
}
}
}

Step 6: Employees by Date of Birth


We also need to get all employees born on a particular date. Since we are now
returning a collection of employees rather than a single one, the implementation
changes very slightly.

public class EmployeeRepository : IEmployeeRepository


{
//...

public async Task<List<Employee>> GetByDateOfBirth(DateTime dateOfBirth)


{
using (IDbConnection conn = Connection)
{
string sQuery = "SELECT ID, FirstName, LastName, DateOfBirth FROM Employe
conn.Open();
var result = await conn.QueryAsync<Employee>(sQuery, new { DateOfBirth =
return result.ToList();
}
}
}

Step 7: Implement the Controller


The nal step is creating a controller to which our EmployeeRepository can be
injected. Here it is:

[Route("api/[controller]")]
[ApiController]
public class EmployeeController : ControllerBase
{
private readonly IEmployeeRepository _employeeRepo;

public EmployeeController(IEmployeeRepository employeeRepo)


{
_employeeRepo = employeeRepo;
}

[HttpGet]
[Route("{id}")]
public async Task<ActionResult<Employee>> GetByID(int id)
{
return await _employeeRepo.GetByID(id);
}

[HttpGet]
[Route("dob/{dateOfBirth}")]
public async Task<ActionResult<List<Employee>>> GetByID(DateTime dateOfBirth)
{
return await _employeeRepo.GetByDateOfBirth(dateOfBirth);
}
}

Summary
That's it! We've implemented Dapper into our ASP.NET Core 2.1 application! Take
a look at the sample project over on GitHub if you want to see the whole thing.

With this infrastructure in place, using Dapper throughout the rest of my team's
project should be a breeze. Or, at least, we hopefully won't encounter any project-
sinking icebergs. All aboooooard!

Did I miss something about ASP.NET Core, Dapper, or anything else in this
tutorial? Did you take my sample project and make it better? I want to hear about
it! Sound o in the comments!

Happy Coding!

Matthew Jones
I'm a husband, father, developer, speaker, blogger, lots of things! Buy me a coffee

39 Comments Exception Not Found 


1 Login

 Recommend 4 t Tweet f Share Sort by Best

Join the discussion…

LOG IN WITH
OR SIGN UP WITH DISQUS ?

Name

Brent Arias • a year ago


Dapper will open the connection for you, so no need to explicitly call conn.Open(). Also, instead of a repository
interface, consider a command/query interface as described here: https://cuttingedge.it/blog...
16 △ ▽ 1 • Reply • Share ›

jon49 • a year ago • edited


Looks great. This suggestion is a bit outside the scope of the post but I do think it is a worthwhile point. All I would do
is add some static typing and formatting to the query with minimal performance implications. It is a bit of a pain to
write and a bit uglier but I think the long term maintainability makes it worth it.

string sQuery = $@"


SELECT
{nameof(Employee.ID)},
{nameof(Employee.FirstName)},
{nameof(Employee.LastName)},
{nameof(Employee.DateOfBirth)}
FROM {nameof(Employee)}
WHERE {nameof(Employee.DateOfBirth)} = @{nameof(dateOfBirth)};";

And you can also do this which also adds to the maintainability of the application (then you know your query param
matches your actual query:

var result = await conn.QueryAsync<employee>(sQuery, new { dateOfBirth });

9△ ▽ • Reply • Share ›

John Marsing > jon49 • a year ago


Nice, Auto generating that would be helpfull
△ ▽ • Reply • Share ›

jon49 > John Marsing • a year ago


I think the power of Dapper comes when you start making abstractions on the SQL code itself. But if
you aren't doing that then, yes, auto generating makes more sense since you can bypass the
unneeded abstractions that Dapper uses - which makes your code even faster. Granted Dapper is
already pretty fast; but even according to their benchmarks just writing the ado.net code directly is the
fastest. You can use T4 templates or libraries/extensions like these (unfortunately Query First is not
being kept up-to-date):

https://github.com/bbsimonb...

http://fsprojects.github.io...
△ ▽ • Reply • Share ›

jon49 > John Marsing • a year ago


My original reply was me thinking you were talking about something else. But yes, that is the power of
Dapper. You can create your own abstractions. So, you wouldn't really need to do all the `nameof`s you
would probably map directly from you class and have other abstractions on top of it. The `nameof`s
would probably be more useful for actual concrete parts of the query that you generate - mostly the
predicate parts from my experience.
△ ▽ 1 • Reply • Share ›

Tim Loy • a year ago


You are using QueryAsync<employee>() and then FirstOrDefault(), but maybe it would be better to use
QueryFirstOrDefaultAsync<> method here.
7△ ▽ • Reply • Share ›

madhan kumar • a year ago


Good article . My suggestion is use the stored procedures ,instead of plain Sql queries
Ex : var parameters = new DynamicParameters();
parameters.Add("@DateOfBirth", dateOfBirth);
var res = conn.Execute("GET_Employee", parameters, null, 0, commandType: CommandType.StoredProcedure);
because i used Stored procedures in my asp.net core 2.0 application with Dapper . advantage can main DB layer
easy
Thank you
3△ ▽ • Reply • Share ›

Janus Knudsen > madhan kumar • a year ago


Why would you use SP instead? Imho SP's are meant for DB-operations that primarily is running via the
JobAgent or maybe called manually.
1△ ▽ • Reply • Share ›

thargan > madhan kumar • a year ago


This was the pattern 10 years ago due to speed but now that the query languages are not a bottle neck this
actually adds another layer and makes it more difficult to maintain unless your team has separate roles for
developer and DB developer.
△ ▽ • Reply • Share ›

Dryxxxa > thargan • 10 months ago


Because C# code is not the correct place for SQL queries.
Queries inside code look fine as long as they are small. But you could've used, say, EF if everything
you do with the DB is simple CRUD.
Once there're subqueries, window functions, any other difficult stuff in your queries, they start looking
abysmal in code. That's when you need to organize your sql code, at the very least to have access to
code highlighting. Storing your sql code as stored procedures in a separate place (say, a dbproj) helps
with that. After all, if you use Dapper, you mostly likely have non-autogenerated tables and indexes and
have to store their code somewhere.
△ ▽ 1 • Reply • Share ›

Boby moor > Dryxxxa • a month ago


You can tell exactly the same about store procedures. Hard to read, hard to maintain, no
context whatsover.
△ ▽ • Reply • Share ›

Andrew McClenaghan • a year ago


Another great project that provides a very similar implementation out of the box to what you produced is
https://github.com/jonwagne... in their Auto Interface Implementation https://github.com/jonwagne...
2△ ▽ • Reply • Share ›

Pathum Lakshan • a year ago • edited


Understandable, Detailed, Superb Article.

Thank you Matthew Jones,... :-) !!!


1△ ▽ • Reply • Share ›

Mike Roosa • 8 days ago


Excellent article Matthew. I have a somewhat related question. Let's say your Employee class contained several more
properties and you really only need to return a couple of those properties for the GetByDateOfBirth method. Maybe
you just want the ID and First/Last Name to display in a dropdown. Do you typically create another class for
something like BaseEmployee or what?
△ ▽ • Reply • Share ›

Jaime Bennett • 3 months ago


Thanks for the great article. I have been using this code successfully for a while but I've recently run into an issue. I
recently began using Azure's Hyperscale SQL service tier with secondary read-only replica(s). The queries in SQL
server management studio all return in less than a second when connecting directly to a secondary replica. However,
when using the same code, if I modify the connection string to include "ApplicationIntent=READONLY;", it seems like
Dapper is taking 10-30 seconds to map the query result to the object. Any ideas?
△ ▽ • Reply • Share ›

Rahul M • 3 months ago • edited


Is there a specific benefit to how it is done here? I would really like to know if I have been doing it wrong.

I don't understand why IDbConnection needs to be opened in the repository like above. I would have used below
code in ConfigureServices and then injected IDbConnection into repository/controller and used it that way. There is
no need to open SqlConnection as dapper would handle it for you.

services.AddTransient<idbconnection>(db => new SqlConnection(


Configuration.GetConnectionString("MyConnectionString")));
△ ▽ • Reply • Share ›

Darwin Q • 4 months ago


Big Thanks Matthew and Brent removing the conn.Open();
△ ▽ • Reply • Share ›

BobbyQuick • 4 months ago • edited


If you're already using EF Core, then there's an easy way to set up the connection.

Just grab your DbContext and get the connection from there.

MyDbContext _db; // Wired in from DI probably

using (IDbConnection conn = _db.Database.GetDbConnection())


{
var result = async conn.QueryAsync<foo>("...");
}

It's nice to us EF Core for the simple stuff and insert/update ops, then use Dapper to map your complex queries. EF
Core seems to be weak at that IMHO.
△ ▽ • Reply • Share ›

PEtter Ekrann • 7 months ago


Just a thought.. You should not pass the IConfiguration into you repo.
Pass the ISqlConnection instead to avoid the "service locator pattern".
Will be hard to spot the configuration if you project grows
△ ▽ • Reply • Share ›

Heinrich Teitge • 8 months ago


Thanks Matthew, appreciate the time you took to explain and give a nice example to work from. Sometimes you just
need to see code to get started.
△ ▽ • Reply • Share ›

Make Luv • a year ago


Nice post. Thanks.
△ ▽ • Reply • Share ›

Rashmin Javiya • a year ago


In HTTP protocol, client anyway has to wait till server process the request and return HTML/JSON. What is
significant/different between Async and sync operation? I mean there is no GUI which may freeze if sync operation
used.

Async method

[HttpGet]
[Route("{id}")]
public async Task<actionresult<employee>> GetByID(int id)
{
return await _employeeRepo.GetAsyncByID(id);
}

Sync method

[HttpGet]
[Route("{id}")]
public ActionResult<employee> GetByID(int id)
{
return _employeeRepo.GetByID(id);
}

Async will not freeze the main thread but then how does it make any difference when there is no UI
△ ▽ • Reply • Share ›

F. Donnet > Rashmin Javiya • 8 months ago


It0s for scalabillity. You will be able to serve more http requests. You thread is available (free) when you call
the database and can be used for another request. And when your DB will give the result you will take an
available thread again. Your web server will thank you if you need to serve a lot of concurrent requests.
△ ▽ • Reply • Share ›

Rashmin Javiya > F. Donnet • 8 months ago


Thanks :)
△ ▽ • Reply • Share ›

Himalaya Garg • a year ago


This is among the finest and most usable code. Working like a charm.
△ ▽ • Reply • Share ›

Hector Perez • a year ago


Thank you very much, you save me a lot of time. Nice weekend!
△ ▽ • Reply • Share ›

Vid Mioković • a year ago


Hi,

As far as I know you don't need to dispose dbConnection nor do you need to explicitly open it. Dapper does this all for
you. This is true for simple queries, for more complex one where you have more than one query doing the job and
with transactions in the mix then its better to open dbConnection by yourself where you need it, and close/dispose of
it where appropriate.
△ ▽ • Reply • Share ›

jon49 • a year ago


Recently I've learned that Dapper isn't really under active development anymore. I'm sure they will still fix egregious
bugs, if you find any. But as far as fixing outstanding issues that really need to be fixed it's unlikely to happen. I just
ran into this problem recently and found out that the original issue was raised over four years ago. But they decided
that they would like to wait unit version 2.0 to implement the fix. Version 2.0 roadmap was created at the beginning of
2017 but hasn't really been worked on.

I understand that the authors have other projects they are working on so I'm not too upset with them. Just a bit
disappointed that one of the more popular ORMs out there in .NET is a bit dead in the water as far as active new
development goes.
△ ▽ • Reply • Share ›

jon49 > jon49 • a year ago


I wonder if part of the reason that Dapper isn't really under active development anymore is because Entity
Framework is almost on par with Dapper in speed and can take a string for queries too. So, it seems there
isn't a need for Dapper anymore. Even Stack Overflow uses Entity Framework. It seems we are all working
under an old paradigm about Dapper being the go to for speed.
△ ▽ • Reply • Share ›

Janus Knudsen > jon49 • a year ago


Hi Jon
Can you elaborate a bit more on that statement about SO?
△ ▽ • Reply • Share ›

jon49 > Janus Knudsen • a year ago


FYI, I replied but since it had a couple of links the comment needs to be approved first.
1△ ▽ • Reply • Share ›

jon49 > Janus Knudsen • a year ago


I guess I was spreading a bit of misinformation here. It looks like SO uses Dapper and Entity
Framework Core. https://meta.stackexchange....

Also, here's a couple of videos from a couple of years ago on what SO does.
https://groupby.org/confere...
△ ▽ • Reply • Share ›

Janus Knudsen > jon49 • a year ago


Yes, I see.. okay, last time I checked SO was only using Dapper. But this new information is
actually quite interesting. Thank you :)
△ ▽ • Reply • Share ›

jjestrellaa • a year ago


Is adding each repository as a service in the startup class the only option?
△ ▽ • Reply • Share ›

peinearydevelopment • a year ago • edited


Thanks so much for the post! I just started looking into Dapper for a project as well. With Entity Framework, I've really
appreciated the ability to use SQLite for testing. I didn't see anything like that for Dapper. I started creating a
project(https://github.com/peineary... to help enable that. Are there any options currently out there that you are aware
of?

Thanks again!
△ ▽ • Reply • Share ›

miki albert • a year ago


you could also use some syntactic sugar to do basic queries (especially basic queries!) https://github.com/MoonStor...

this way, you won't have to write again and again select query strings
△ ▽ • Reply • Share ›

Thunder • a year ago • edited


Thanks for article but I'm wondering how we can manage transaction with Dapper and Repository pattern and
another question can I use my existing poco classes used by Entity Framework with Dapper?
△ ▽ • Reply • Share ›

Thomas > Thunder • a year ago


This video show some example on how to use transactions:

1△ ▽ • Reply • Share ›

Thomas > Thunder • a year ago


There is some examples of transactions in this video:

1△ ▽ • Reply • Share ›

ALSO ON EXCEPTION NOT FOUND

Ten Seconds, Identity, and 20% Memory Loss: Why A Definitive FizzBuzz Solution Guide in C#
You Need Backups 25 comments • 7 months ago
4 comments • 4 months ago Whiteknight — I find another purpose for FizzBuzz in
Wellspring — It's probably some cardinal sin to reply to Avatarparticular is that it helps to weed out some people on the
Avatarthree blog posts with one comment, but I other end of the spectrum with a tendency to over-
(a) appreciated your post regarding outrage --> I think

Insertion Sort in C# - Exception Not Found Patience, Outrage Culture, and Mr. Berger's Class
3 comments • 3 months ago 8 comments • 9 months ago
James Curran — It should be noted the an Insertion Sort is Matthew Jones — I'm going to use the comments to
Avatarvery efficient on a linked-list (which allows O(1) insertions Avatarinclude a few details that I believe are relevant but that
into the middle of the list, rather than the O(n) required for didn't fit into the main story.1. There is no evidence that Mr.

✉ Subscribe d Add Disqus to your siteAdd DisqusAdd 🔒 Disqus' Privacy PolicyPrivacy PolicyPrivacy

dapper
Dapper vs Entity Framework vs ADO.NET Performance Benchmarking

1 post →

 SWAGGER  STORIES

Adding Swagger to ASP.NET Core Confessions of a "Well, Actually..."


Web API using XML Documentation Guy
Swagger and XML Comments make documenting It was almost imperceptible. A slight shift in her
your ASP.NET Core APIs a breeze! Or was it a gaze, a miniscule shake of her head, a ash behind
cinch?... Either way, check it out! her eyes. She knew, and then I understood. I had
done it again.

 A YEAR AGO 5 MIN READ  A YEAR AGO 3 MIN READ

You might also like