Open-source project
DapperLib/Dapper avatar
DapperLib/Dapper

Dapper: a .NET micro-ORM built on ADO.NET extension methods

Dapper - a simple object mapper for .Net

18,397 stars3,668 forksC#NOASSERTION

At a glance

What is it?
Dapper extends DbConnection with Query and Execute helpers so you keep writing SQL while getting typed object mapping. It suits teams that want control over queries without a full ORM, and it assumes you already know your database.
Who is it for?
Adopt Dapper when you want SQL in your source and object mapping without a change tracker; skip it if you need migrations, lazy loading or a model-first workflow. Before committing, verify that the package variant you pick matches your project, since the README lists Dapper, Dapper.StrongName, Dapper.EntityFramework, Dapper.Rainbow and Dapper.SqlBuilder as separate packages with different purposes, and confirm your target framework is covered by the current release on NuGet.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 7 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Dapper solves for .NET developers who still write SQL

Dapper is a NuGet library you add to an existing project. According to the README, it enhances your ADO.NET connections through extension methods on your DbConnection instance, giving you a simple API for invoking SQL. That framing matters: Dapper does not replace ADO.NET, it sits on top of it. You keep the connection object you already open and close, and you keep writing the SQL yourself.

The audience is narrow and specific. If you are comfortable with SQL, have an existing database schema, and find yourself writing the same DataReader loop over and over to turn rows into objects, Dapper removes that loop. The README's first example defines a Dog class with Age, Id, Name and Weight properties and then calls connection.Query<Dog> with a select statement, asserting that the returned list has one item with the expected Id. No mapping configuration, no entity registration, no context class.

It is the wrong tool for anyone who wants the database generated from code. There is no migration story in the README, no schema management, no change tracking. Dapper assumes the schema exists and that you, not the library, are responsible for its shape.

How the DbConnection extension methods map rows to objects

The mechanism is extension methods plus reflection-based materialisation. The README lists three key APIs: connection.Execute for insert, update and delete statements, connection.Query<T> for multi-row queries, and connection.QuerySingle<T> for single-row queries, with Single, First, SingleOrDefault and FirstOrDefault variants named in the comment. Each takes a SQL string and an optional args argument.

That args argument is where the parameter handling lives. The README says it can be a simple POCO including anonymous types for named parameters, a Dictionary<string,object>, or a DynamicParameters instance. The Dog example passes an anonymous object with an Age of null and a Guid, and the assertions confirm that a nullable int property comes back null while the Guid round-trips. So parameter names in the SQL are matched to property names on the object you pass, and nulls survive the trip.

The dynamic path is separate. Calling connection.Query without a type parameter returns a dynamic list, and the README shows a union query whose two rows are read back as rows[0].A, rows[0].B, rows[1].A and rows[1].B. That is useful for ad hoc shapes, but you give up compile-time checking on the property names. The README also notes support for both synchronous and asynchronous data access and for buffered and non-buffered queries, which is the main lever you have over memory when a result set is large.

Installing Dapper and running your first typed query

Dapper ships as a NuGet package. The README's package table lists Dapper, Dapper.EntityFramework, Dapper.EntityFramework.StrongName, Dapper.Rainbow, Dapper.SqlBuilder and Dapper.StrongName, and the package purposes section says Dapper is the core library while Dapper.Rainbow is a micro-ORM implemented on Dapper that provides CRUD helpers. Start with the core package unless you specifically need one of the others.

Add it to a project with the .NET CLI:

bash
dotnet add package Dapper

If your project needs a strong-named assembly, the README lists Dapper.StrongName as a separate package rather than a build flag, so you would add that one instead:

bash
dotnet add package Dapper.StrongName

With the package referenced, the smallest real use is a typed query against an open connection. The README's Dog example is the template: declare a class whose property names match the columns or aliases you select, then call Query<T>. Note that IgnoredProperty in that example is a computed get-only property, and the assertions still pass, which tells you the mapper tolerates properties it cannot set.

csharp
public class Dog
{
    public int? Age { get; set; }
    public Guid Id { get; set; }
    public string Name { get; set; }
    public float? Weight { get; set; }

    public int IgnoredProperty { get { return 1; } }
}

The README shows the call and the assertions that go with it:

csharp
var guid = Guid.NewGuid();
var dog = connection.Query<Dog>("select Age = @Age, Id = @Id", new { Age = (int?)null, Id = guid });

Assert.Equal(1, dog.Count());
Assert.Null(dog.First().Age);
Assert.Equal(guid, dog.First().Id);

What you should see is a single-element sequence. The count assertion is 1, the Age assertion is null because a nullable int was passed as null, and the Id assertion matches the generated Guid. For statements that return no rows, the README uses Execute and asserts the returned count, which is the number of affected rows:

csharp
var count = connection.Execute(@"
  set nocount on
  create table #t(i int)
  set nocount off
  insert #t
  select @a a union all select @b
  set nocount on
  drop table #t", new {a=1, b=2 });
Assert.Equal(2, count);

The README states the same signature also lets you execute a command multiple times, which it describes as convenient for bulk-loading data. That is the point where Dapper stops being a mapper and starts being a batch executor, and it is worth knowing before you reach for a separate bulk-copy library.

Where Dapper stops helping: mapping limits and schema drift

The trade-off is explicit in the design. Dapper maps what your SQL returns. If a column is renamed, the query still runs and the property silently stays at its default value, because nothing in the README describes validation that every selected column found a destination property. That is the classic failure mode of a micro-ORM and it is worth stating plainly: your integration tests, not the library, are what catch a renamed column.

The README does not document rollback behaviour, transaction scoping beyond the underlying ADO.NET connection, or how nested object graphs are handled. Those gaps are not accidents, they are the boundary of the project. Dapper is deliberately not an ORM in the Entity Framework sense. There is no change tracker in the API surface the README describes, no lazy loading, no migrations, no LINQ query provider. Everything you would get from those features you write yourself.

The dynamic query path carries a second cost. When you call Query without a type, the README's example accesses rows[0].A and rows[0].B, which means the property names are resolved at runtime. A typo becomes a runtime error rather than a compile error, and you lose the ability to grep for usages of a property. For a quick diagnostic query that is fine. For code that ships, the typed overload is the safer default.

One more constraint worth noting: the README lists Dapper.EntityFramework as extension handlers for EntityFramework. That is a bridge for people already inside Entity Framework, not a reason to adopt Dapper. If you are already using a full ORM, adding Dapper on top means two query paths in one codebase, and the README gives no guidance on when to prefer one.

Dapper compared with a full ORM

The real alternative is an object-relational mapper such as Entity Framework, and the difference is not performance claims, it is where the model lives. With a full ORM, you define classes and the tool generates or migrates the schema, tracks changes to loaded entities, and translates LINQ expressions into SQL. With Dapper, the SQL is the source of truth and the classes are just shapes to pour rows into.

The README's own package list makes this concrete. Dapper.EntityFramework exists as extension handlers for EntityFramework, which means the two are expected to coexist in some codebases rather than compete outright. A team can use Entity Framework for writes and Dapper for read-heavy queries that need hand-tuned SQL. That is a legitimate pattern, but it doubles the surface area you have to reason about, and the README offers no rules for the split.

If your queries are simple CRUD against a schema you control, a full ORM will write most of that SQL for you and you will not miss Dapper. If your queries are analytical, use hints, or need to be reviewed by a DBA, Dapper lets the SQL stay readable in the source file. The deciding question is whether you want the database or the code to be authoritative. Dapper picks the database.

Maintenance, licensing and what the repository tells you

The repository is not archived, and the last push was on 2026-09-12. The most recent release listed is 2.1.86 on the same date, following 2.1.79 on 2026-05-16 and 2.1.72 on 2026-03-06. That cadence suggests patches arrive between minor bumps rather than on a fixed schedule, so pinning an exact version and reading the release notes at https://github.com/DapperLib/Dapper/releases is the practical upgrade path. The README points there rather than duplicating a changelog.

On licensing, the repository reports NOASSERTION, which means GitHub could not match the licence file to a known identifier. A License.txt file exists at the top level alongside NonCLA.md. Because the identifier is unresolved, a team with strict licence review should read License.txt directly rather than assume a standard permissive licence. That is a factual observation about the repository metadata, not legal advice.

The project's history is worth knowing for procurement purposes: the README states Dapper was originally developed for and by Stack Overflow and is free and open source software, with sponsorship invited. Dapper Plus is named as a major sponsor and AWS is named as a sponsor since October 2023 through the .NET on AWS Open Source Software Fund. Sponsorship of this kind does not change the licence, but it does tell you who has an interest in the project continuing.

Upgrade cost is low by design. Dapper is a library of extension methods on DbConnection, so the API you depend on is the one in the README: Execute, Query, QuerySingle and their variants. There is no runtime host, no configuration file and no service to operate. The cost of an upgrade is recompiling and re-running your own tests, which is also the only thing that will catch a mapping regression.

Editorial conclusion

Adopt Dapper when you want SQL in your source and object mapping without a change tracker; skip it if you need migrations, lazy loading or a model-first workflow. Before committing, verify that the package variant you pick matches your project, since the README lists Dapper, Dapper.StrongName, Dapper.EntityFramework, Dapper.Rainbow and Dapper.SqlBuilder as separate packages with different purposes, and confirm your target framework is covered by the current release on NuGet.

Frequently asked questions

How do I install Dapper in Visual Studio 2022?

Install it as a NuGet package. The README lists Dapper as the core library on nuget.org, and Dapper.StrongName as a separate package if your project needs a strong-named assembly.

How do I install Dapper?

Add the Dapper package from NuGet to your project. The README's package table points at https://www.nuget.org/packages/Dapper/ for the core library, with Dapper.EntityFramework, Dapper.Rainbow and Dapper.SqlBuilder as separate packages for other purposes.

How do I use Dapper in C#?

Call the extension methods on an open DbConnection. The README's key APIs are connection.Execute for insert, update and delete, connection.Query<T> for multi-row queries, and connection.QuerySingle<T> for single-row queries, each taking a SQL string and an optional args object.

How do I use Dapper in .NET Core?

The README describes Dapper as a NuGet library that enhances your ADO.NET connections via extension methods on DbConnection, with support for synchronous and asynchronous data access. That applies to .NET Core projects the same way, since the API is built on DbConnection.

Official sources

  1. DapperLib/Dapper on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dapperlib-dapper.svg)](https://hysenlabs.com/projects/dapperlib-dapper)