SlideShare a Scribd company logo
Advanced Data Access
with Dapper
@Dave_Paquette
Microsoft MVP (ASP.NET/IIS)
contactme@davepaquette.com
http://www.davepaquette.com
Advanced .NET Data Access with Dapper
Data Access
How did we get here?
Why is this so hard?
public class Foo
{
//…some properties
}
SQL Server
Data Access in .NET
• In the beginning there was System.Data
• IDbConnection
• IDbCommand
• IDataReader
• IDbTransaction
Sytem.Data - Reading Records
var results = new List<Employee>();
using (SqlConnection connection = new SqlConnection(Settings.ConnectionString))
{
SqlCommand command = new SqlCommand(“SELECT * FROM Employees”, connection);
connection.Open();
IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
results.Add(ReadSingleRow(reader));
}
reader.Close();
}
return results;
The ORMs will save us
• Hide details of database
• Generate SQL based on object model and configuration
• ChangeTracking
• Complex mapping strategies
• Many-to-many relationships
• Inheritance
Popular ORMs
•Entity Framework
•nHibernate?
•Linq2Sql?
ORM Pain Points
• Black box code generation –What is going on?
• Performance Problems
• Eager Loading vs Lazy Loading
• Complex Inheritance Chains
• Dealing with disconnected entities (in a web context)
The Micro-ORMs will save us!
• Query --> Objects
• Usually focused on speed
• Light on features
Popular Micro-ORMs
• Dapper
• PetaPOCO
• Massive
• Simple.Data
Dapper
• Used in production at Stack Exchange
• Super fast and easy to use
Performance of SELECT mapping over 500
iterations - POCO serialization
https://github.com/StackExchange/Dapper#performance
ORM Method Mean Allocated
LINQ to DB 'First (Compiled)' 78.75 us 2.66 KB
LINQ to DB Query<T> 80.38 us 6.87 KB
Hand Coded SqlCommand 87.16 us 12.24 KB
Dapper QueryFirstOrDefault<dynamic> 87.80 us 13.5 KB
Dapper QueryFirstOrDefault<T> 91.51 us 13.46 KB
Massive 'Query (dynamic)' 96.18 us 14.19 KB
PetaPoco 'Fetch<T> (Fast)' 96.57 us 13.65 KB
EF 6 SqlQuery 143.86 us 27.86 KB
EF Core 'First (Compiled)' 148.42 us 16.08 KB
NHibernate Get<T> 196.88 us 32.5 KB
EF Core First 197.91 us 20.25 KB
NHibernate HQL 207.84 us 35 KB
EF Core 'First (NoTracking)' 213.58 us 21.36 KB
How can it be that fast?
• Dapper dynamically writes code for you
• Emits IL code for tasks like loading a data
reader into an object
• https://github.com/StackExchange/Dapper/blo
b/master/Dapper/SqlMapper.cs#L3078
Dapper works on Database Connections
A set of extension methods on IDbConnection
Aircraft aircraft;
using (var connection = new SqlConnection(_connectionString))
{
await connection.OpenAsync(); //Optional
var query = "SELECT * FROM Aircraft WHERE Id = @Id";
Aircraft aircraft = await connection.QuerySingleAsync<Aircraft>(query, new {Id = id});
}
Querying Simple Objects
Aircraft aircraft = await connection.QuerySingleAsync<Aircraft>(query, new {Id = id});
IEnumerable<Aircraft> aircraft = await connection.QueryAsync<Aircraft>(query);
Loading Related Objects – Multi-Mapping
• Write a single query that returns all the data in a single row
scheduledFlights =
await connection.QueryAsync<ScheduledFlight, Airport, ScheduledFlight>(query,
(flight, airport) => {
flight.Airport = airport;
return flight;
},
new{FromCode = from} );
Multi-Mapping Caveats
• Data duplication
• Query returns a bloated data set
• Multiple instances of an object that represent the same thing
• This is totally fine forOne-to-One relationships
• No duplication here
Loading Related Objects – Multiple Queries
• Get data using multiple queries and wire them up yourself
• Still executed in a single command that returns multiple results sets
using (var multi = await connection.QueryMultipleAsync(query, new{FromCode = from} ))
{
scheduledFlights = multi.Read<ScheduledFlight>();
var airports = multi.Read<Airport>().ToDictionary(a => a.Id);
foreach(var flight in scheduledFlights)
{
flight.Airport = airports[flight.AirportId];
}
}
Multi-Mapping vs Multiple Queries
100 ScheduledFlight Records 1,000 ScheduledFlight Records
Method Mean
MultiMapping 926.5 us
MultipleResultSets 705.9 us
Method Mean
MultiMapping 5.098 ms
MultipleResultSets 2.809 ms
https://www.davepaquette.com/archive/2018/04/10/loading-related-entities-many-to-one-part-2.aspx
AirportSchedule
Date
Airport
Departures
Arrivals
Airport
Id
Code
City
Province
Country
Flight
Id
ScheduledFlight
ScheduledDeparture
ActualDeparture
ScheduledArrival
ActualArrival
ScheduledFlight
Id
FlightNumber
DepartureAirport
ArrivalAirport
…
1
1
1
**
1
1
1
1
1
* *
Loading More Complex Object Graphs
Loading More Complex Object Graphs
Paging through large collections
• Use an OFFSET FETCH query
• Include a total count in the result
SELECT * FROM Flight f
INNER JOIN ScheduledFlight sf
ON f.ScheduledFlightId = sf.Id
ORDER BY Day, FlightNumber
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY
SELECT COUNT(*) FROM Flight f
INNER JOIN ScheduledFlight sf
ON f.ScheduledFlightId = sf.Id
Insert / Update / Delete
• Use the ExecuteAsync method
• Built-in support for batch inserts
await connection.ExecuteAsync(
@"INSERT INTO Flight(ScheduledFlightId, Day, ScheduledDeparture,
ScheduledArrival)
VALUES(@ScheduledFlightId, @Day, @ScheduledDeparture, @ScheduledArrival)",
flights);
Buffering
•Working with really large result sets?
• Consider setting buffering=false for queries
Dapper Contrib
• Generates SQL for simple CRUD operations
Questions?
Check out my blog posts
http://bit.ly/dapperseries
www.davepaquette.com
westerndevs.com
aspnetmonsters.com
Blog(s)
Twitter @Dave_Paquette
Email contactme@davepaquette.com
Thanks!

More Related Content

What's hot (20)

PDF
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Nalee Jang
 
PDF
Gerenciamento de Backup e Recovery com Barman PGConfBrasil2019
CLEYSSON LIMA
 
PDF
MySQL partitions tutorial
Giuseppe Maxia
 
PDF
Puppeteer can automate that! - AmsterdamJS
Önder Ceylan
 
PDF
Java spring framework
Rajiv Gupta
 
PDF
malloc & vmalloc in Linux
Adrian Huang
 
PDF
LCU14 302- How to port OP-TEE to another platform
Linaro
 
PPTX
Linux Kernel Programming
Nalin Sharma
 
PDF
Profiling your Applications using the Linux Perf Tools
emBO_Conference
 
PDF
Indexes in postgres
Louise Grandjonc
 
PDF
Patroni - HA PostgreSQL made easy
Alexander Kukushkin
 
PDF
Linux Internals - Part I
Emertxe Information Technologies Pvt Ltd
 
PDF
Node ppt
Tamil Selvan R S
 
PPTX
Spring Boot
Jiayun Zhou
 
PDF
semaphore & mutex.pdf
Adrian Huang
 
PDF
Fun with Network Interfaces
Kernel TLV
 
PPTX
PostgreSQL- An Introduction
Smita Prasad
 
PDF
[오픈소스컨설팅] Ansible을 활용한 운영 자동화 교육
Ji-Woong Choi
 
PDF
Waits monitoring in PostgreSQL
Ildus Kurbangaliev
 
PDF
MySQL Performance Tuning: Top 10 Tips
OSSCube
 
Red Hat OpenStack 17 저자직강+스터디그룹_1주차
Nalee Jang
 
Gerenciamento de Backup e Recovery com Barman PGConfBrasil2019
CLEYSSON LIMA
 
MySQL partitions tutorial
Giuseppe Maxia
 
Puppeteer can automate that! - AmsterdamJS
Önder Ceylan
 
Java spring framework
Rajiv Gupta
 
malloc & vmalloc in Linux
Adrian Huang
 
LCU14 302- How to port OP-TEE to another platform
Linaro
 
Linux Kernel Programming
Nalin Sharma
 
Profiling your Applications using the Linux Perf Tools
emBO_Conference
 
Indexes in postgres
Louise Grandjonc
 
Patroni - HA PostgreSQL made easy
Alexander Kukushkin
 
Spring Boot
Jiayun Zhou
 
semaphore & mutex.pdf
Adrian Huang
 
Fun with Network Interfaces
Kernel TLV
 
PostgreSQL- An Introduction
Smita Prasad
 
[오픈소스컨설팅] Ansible을 활용한 운영 자동화 교육
Ji-Woong Choi
 
Waits monitoring in PostgreSQL
Ildus Kurbangaliev
 
MySQL Performance Tuning: Top 10 Tips
OSSCube
 

Similar to Advanced .NET Data Access with Dapper (20)

PPTX
Advanced data access with Dapper
David Paquette
 
PPTX
Orms vs Micro-ORMs
David Paquette
 
PPT
JDBC Connecticity.ppt
Swapnil Kale
 
PDF
Play framework productivity formula
Sorin Chiprian
 
PPTX
Spark etl
Imran Rashid
 
PPTX
Dapper performance
Suresh Loganatha
 
PDF
UEMB200: Next Generation of Endpoint Management Architecture and Discovery Se...
Ivanti
 
PPT
nodejs_at_a_glance.ppt
WalaSidhom1
 
PDF
Hw09 Sqoop Database Import For Hadoop
Cloudera, Inc.
 
PPT
nodejs_at_a_glance, understanding java script
mohammedarshadhussai4
 
PDF
NoSQL meets Microservices - Michael Hackstein
distributed matters
 
PPTX
Keeping Spark on Track: Productionizing Spark for ETL
Databricks
 
PPT
Zend Con 2008 Slides
mkherlakian
 
PDF
Complex Made Simple: Sleep Better with TorqueBox
bobmcwhirter
 
PPTX
Sherlock Homepage (Maarten Balliauw)
Visug
 
PPTX
Sherlock Homepage - A detective story about running large web services (VISUG...
Maarten Balliauw
 
KEY
Writing robust Node.js applications
Tom Croucher
 
PDF
Breaking Parser Logic: Take Your Path Normalization Off and Pop 0days Out!
Priyanka Aash
 
PPTX
Sherlock Homepage - A detective story about running large web services - NDC ...
Maarten Balliauw
 
ODP
Web program-peformance-optimization
xiaojueqq12345
 
Advanced data access with Dapper
David Paquette
 
Orms vs Micro-ORMs
David Paquette
 
JDBC Connecticity.ppt
Swapnil Kale
 
Play framework productivity formula
Sorin Chiprian
 
Spark etl
Imran Rashid
 
Dapper performance
Suresh Loganatha
 
UEMB200: Next Generation of Endpoint Management Architecture and Discovery Se...
Ivanti
 
nodejs_at_a_glance.ppt
WalaSidhom1
 
Hw09 Sqoop Database Import For Hadoop
Cloudera, Inc.
 
nodejs_at_a_glance, understanding java script
mohammedarshadhussai4
 
NoSQL meets Microservices - Michael Hackstein
distributed matters
 
Keeping Spark on Track: Productionizing Spark for ETL
Databricks
 
Zend Con 2008 Slides
mkherlakian
 
Complex Made Simple: Sleep Better with TorqueBox
bobmcwhirter
 
Sherlock Homepage (Maarten Balliauw)
Visug
 
Sherlock Homepage - A detective story about running large web services (VISUG...
Maarten Balliauw
 
Writing robust Node.js applications
Tom Croucher
 
Breaking Parser Logic: Take Your Path Normalization Off and Pop 0days Out!
Priyanka Aash
 
Sherlock Homepage - A detective story about running large web services - NDC ...
Maarten Balliauw
 
Web program-peformance-optimization
xiaojueqq12345
 
Ad

Recently uploaded (20)

PDF
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
PPTX
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
PDF
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
PDF
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
PDF
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
PPTX
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
PDF
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
PDF
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
PDF
July Patch Tuesday
Ivanti
 
PDF
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
PDF
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
PDF
Blockchain Transactions Explained For Everyone
CIFDAQ
 
PDF
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
PDF
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
PDF
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
PPT
Interview paper part 3, It is based on Interview Prep
SoumyadeepGhosh39
 
PPTX
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
PDF
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
PDF
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
PDF
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
"Beyond English: Navigating the Challenges of Building a Ukrainian-language R...
Fwdays
 
OpenID AuthZEN - Analyst Briefing July 2025
David Brossard
 
[Newgen] NewgenONE Marvin Brochure 1.pdf
darshakparmar
 
New from BookNet Canada for 2025: BNC BiblioShare - Tech Forum 2025
BookNet Canada
 
Jak MŚP w Europie Środkowo-Wschodniej odnajdują się w świecie AI
dominikamizerska1
 
UiPath Academic Alliance Educator Panels: Session 2 - Business Analyst Content
DianaGray10
 
DevBcn - Building 10x Organizations Using Modern Productivity Metrics
Justin Reock
 
SWEBOK Guide and Software Services Engineering Education
Hironori Washizaki
 
July Patch Tuesday
Ivanti
 
Fl Studio 24.2.2 Build 4597 Crack for Windows Free Download 2025
faizk77g
 
Smart Trailers 2025 Update with History and Overview
Paul Menig
 
Blockchain Transactions Explained For Everyone
CIFDAQ
 
CIFDAQ Weekly Market Wrap for 11th July 2025
CIFDAQ
 
"AI Transformation: Directions and Challenges", Pavlo Shaternik
Fwdays
 
How Startups Are Growing Faster with App Developers in Australia.pdf
India App Developer
 
Interview paper part 3, It is based on Interview Prep
SoumyadeepGhosh39
 
Top iOS App Development Company in the USA for Innovative Apps
SynapseIndia
 
NewMind AI - Journal 100 Insights After The 100th Issue
NewMind AI
 
Agentic AI lifecycle for Enterprise Hyper-Automation
Debmalya Biswas
 
CIFDAQ Market Insights for July 7th 2025
CIFDAQ
 
Ad

Advanced .NET Data Access with Dapper

  • 1. Advanced Data Access with Dapper @Dave_Paquette Microsoft MVP (ASP.NET/IIS) [email protected] http://www.davepaquette.com
  • 3. Data Access How did we get here? Why is this so hard? public class Foo { //…some properties } SQL Server
  • 4. Data Access in .NET • In the beginning there was System.Data • IDbConnection • IDbCommand • IDataReader • IDbTransaction
  • 5. Sytem.Data - Reading Records var results = new List<Employee>(); using (SqlConnection connection = new SqlConnection(Settings.ConnectionString)) { SqlCommand command = new SqlCommand(“SELECT * FROM Employees”, connection); connection.Open(); IDataReader reader = command.ExecuteReader(); while (reader.Read()) { results.Add(ReadSingleRow(reader)); } reader.Close(); } return results;
  • 6. The ORMs will save us • Hide details of database • Generate SQL based on object model and configuration • ChangeTracking • Complex mapping strategies • Many-to-many relationships • Inheritance
  • 8. ORM Pain Points • Black box code generation –What is going on? • Performance Problems • Eager Loading vs Lazy Loading • Complex Inheritance Chains • Dealing with disconnected entities (in a web context)
  • 9. The Micro-ORMs will save us! • Query --> Objects • Usually focused on speed • Light on features
  • 10. Popular Micro-ORMs • Dapper • PetaPOCO • Massive • Simple.Data
  • 11. Dapper • Used in production at Stack Exchange • Super fast and easy to use
  • 12. Performance of SELECT mapping over 500 iterations - POCO serialization https://github.com/StackExchange/Dapper#performance ORM Method Mean Allocated LINQ to DB 'First (Compiled)' 78.75 us 2.66 KB LINQ to DB Query<T> 80.38 us 6.87 KB Hand Coded SqlCommand 87.16 us 12.24 KB Dapper QueryFirstOrDefault<dynamic> 87.80 us 13.5 KB Dapper QueryFirstOrDefault<T> 91.51 us 13.46 KB Massive 'Query (dynamic)' 96.18 us 14.19 KB PetaPoco 'Fetch<T> (Fast)' 96.57 us 13.65 KB EF 6 SqlQuery 143.86 us 27.86 KB EF Core 'First (Compiled)' 148.42 us 16.08 KB NHibernate Get<T> 196.88 us 32.5 KB EF Core First 197.91 us 20.25 KB NHibernate HQL 207.84 us 35 KB EF Core 'First (NoTracking)' 213.58 us 21.36 KB
  • 13. How can it be that fast? • Dapper dynamically writes code for you • Emits IL code for tasks like loading a data reader into an object • https://github.com/StackExchange/Dapper/blo b/master/Dapper/SqlMapper.cs#L3078
  • 14. Dapper works on Database Connections A set of extension methods on IDbConnection Aircraft aircraft; using (var connection = new SqlConnection(_connectionString)) { await connection.OpenAsync(); //Optional var query = "SELECT * FROM Aircraft WHERE Id = @Id"; Aircraft aircraft = await connection.QuerySingleAsync<Aircraft>(query, new {Id = id}); }
  • 15. Querying Simple Objects Aircraft aircraft = await connection.QuerySingleAsync<Aircraft>(query, new {Id = id}); IEnumerable<Aircraft> aircraft = await connection.QueryAsync<Aircraft>(query);
  • 16. Loading Related Objects – Multi-Mapping • Write a single query that returns all the data in a single row scheduledFlights = await connection.QueryAsync<ScheduledFlight, Airport, ScheduledFlight>(query, (flight, airport) => { flight.Airport = airport; return flight; }, new{FromCode = from} );
  • 17. Multi-Mapping Caveats • Data duplication • Query returns a bloated data set • Multiple instances of an object that represent the same thing • This is totally fine forOne-to-One relationships • No duplication here
  • 18. Loading Related Objects – Multiple Queries • Get data using multiple queries and wire them up yourself • Still executed in a single command that returns multiple results sets using (var multi = await connection.QueryMultipleAsync(query, new{FromCode = from} )) { scheduledFlights = multi.Read<ScheduledFlight>(); var airports = multi.Read<Airport>().ToDictionary(a => a.Id); foreach(var flight in scheduledFlights) { flight.Airport = airports[flight.AirportId]; } }
  • 19. Multi-Mapping vs Multiple Queries 100 ScheduledFlight Records 1,000 ScheduledFlight Records Method Mean MultiMapping 926.5 us MultipleResultSets 705.9 us Method Mean MultiMapping 5.098 ms MultipleResultSets 2.809 ms https://www.davepaquette.com/archive/2018/04/10/loading-related-entities-many-to-one-part-2.aspx
  • 21. Loading More Complex Object Graphs
  • 22. Paging through large collections • Use an OFFSET FETCH query • Include a total count in the result SELECT * FROM Flight f INNER JOIN ScheduledFlight sf ON f.ScheduledFlightId = sf.Id ORDER BY Day, FlightNumber OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY SELECT COUNT(*) FROM Flight f INNER JOIN ScheduledFlight sf ON f.ScheduledFlightId = sf.Id
  • 23. Insert / Update / Delete • Use the ExecuteAsync method • Built-in support for batch inserts await connection.ExecuteAsync( @"INSERT INTO Flight(ScheduledFlightId, Day, ScheduledDeparture, ScheduledArrival) VALUES(@ScheduledFlightId, @Day, @ScheduledDeparture, @ScheduledArrival)", flights);
  • 24. Buffering •Working with really large result sets? • Consider setting buffering=false for queries
  • 25. Dapper Contrib • Generates SQL for simple CRUD operations
  • 26. Questions? Check out my blog posts http://bit.ly/dapperseries

Editor's Notes

  • #4: Data access has consumed such a huge amount of our time. - Why is that? - What is so hard about this?
  • #5: These 4 interfaces were in the original .NET framework. They have been the basis for ALL database access since then. Each database provider has an implementation of each of these interfaces (eg. SqlConnection) Every ORM or Micro-ORM written in .NET is based on these 4 interfaces.
  • #6: Show sample code for reading and writing data using the raw SQL
  • #7: Swinging the pendulum
  • #21: Demo Start with loading simply the first level (Airport + Arrival and Departure Flights) Using multi-mapping to load the ScheduledFlight info Use multi queries to also load each ScheduledFlight’s Arrival and Departure airports