Dapper Tutorial Dapper

What's Dapper?

Dapper is a micro-ORM created by the team behind Stack Overflow. Dapper is a simple object mapper for .NET and owns the title of King of Micro ORM in terms of speed and is virtually as fast as using a raw ADO.NET data reader. An ORM is an Object Relational Mapper responsible for mapping between a database and a programming language.

  • Dapper is a popular open source Object-Relational Mapping (ORM) Library for .NET.
  • It makes it easy to work with data in your application by mapping objects to tables in a database.
  • Dapper is fast, reliable, and well-tested and has been used in production by some of the world's largest companies for many years.
  • It is very easy to use and has a lot of features that make it a powerful tool for data access.

How does Dapper work?

Dapper provides a simple and concise way to manage your data model without having to write a lot of code. It is also very easy to use, and its code is clean and readable.

Dapper extends the IDbConnection interface by providing helpful extension methods to query your database. It uses dynamic method generation to enable it to inflate POCOs directly from query results. In addition, it allows you to map database columns directly to properties on your POCO.

When using Dapper, all you need is a connection string and a POCO, and then it is a three-step process.

  • Create an IDbConnection object.
  • Write a query to perform CRUD operations.
  • Pass the query as a parameter in any Execute or Query method.

Installation

It is straightforward to install Dapper, you can either download the Dapper NuGet package or clone the Dapper GitHub repository.

To install the Dapper NuGet Package, run the following command in the Package Manager Console:

PM> NuGet\Install-Package Dapper

To clone the Dapper GitHub repository, run the following command in a Git Bash window:

git clone https://github.com/StackExchange/Dapper.git

Requirements

Dapper works with any .NET project. This means that it can be used with the following frameworks:

  • .NET Core 5.0 and above
  • .NET Framework 4.6.1 and above
  • .NET Standard 2.0 and above

(Older version is also supported by using older version of Dapper)

Dapper also requires to add a provider package such as:

  • Microsoft.Data.SqlClient (for SQL Server)
  • System.Data.SqlClient (alternative for SQL Server)
  • Microsoft.Data.Sqlite (for SQLite)
  • Any other provider package!

Dapper works with any database provider since there is no database-specific implementation.

Once you have installed the required NuGet packages, you can start using Dapper in your project.

Methods

Dapper extension methods can be used to perform various operations in the database, such as fetching data, inserting records, updating records, and deleting records.

Dapper will extend your IDbConnection interface with multiple methods and some of the most commonly used dapper extension methods.

  • Execute: It can execute a command one or multiple times.
  • ExecuteReader: It can execute a command and return a reader.
  • Executescalar: It can execute a command and return a scalar value.
  • Query: Used to fetch data from the database.
  • QueryFirst: It can execute a query and map the first result.
  • QueryFirstOrDefault: It can execute a query and map the first result, or a default value if the sequence contains no elements.
  • QuerySingle: It can execute a query and map the first result and throws an exception if there is not exactly one element in the sequence.
  • QuerySingleOrDefault: It can execute a query and map the first result, or a default value if the sequence is empty; this method throws an exception if there is more than one element in the sequence.
  • QueryMultiple: It can execute multiple queries within the same command and map results.
string sqlOrderDetails = "SELECT TOP 5 * FROM OrderDetails;";
string sqlOrderDetail = "SELECT * FROM OrderDetails WHERE OrderDetailID = @OrderDetailID;";
string sqlCustomerInsert = "INSERT INTO Customers (CustomerName) Values (@CustomerName);";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    var orderDetails = connection.Query<OrderDetail>(sqlOrderDetails).ToList();
    var orderDetail = connection.QueryFirstOrDefault<OrderDetail>(sqlOrderDetail, new {OrderDetailID = 1});
    var affectedRows = connection.Execute(sqlCustomerInsert,  new {CustomerName = "Mark"});

    Console.WriteLine(orderDetails.Count);
    Console.WriteLine(affectedRows);

    FiddleHelper.WriteTable(orderDetails);
    FiddleHelper.WriteTable(new List<OrderDetail>() { orderDetail });
}

Try it: .NET Core | .NET Framework

Parameter

Dapper supports many different parameter types. Execute and queries method can use parameters from multiple different ways:

  • Anonymous: Useful for simple queries where you don't need to create a separate class to represent your data.
  • Dynamic: Useful for when you need to create a dynamic list of parameters, or when you need to dynamically change the value of a parameter.
  • List: This allows you to specify multiple parameters on an IN clause by using a list.
  • String: Useful when working with SQL Server stored procedures that accept varchar input parameters.
// Anonymous
var affectedRows = connection.Execute(sql,
                    new {Kind = InvoiceKind.WebInvoice, Code = "Single_Insert_1"},
                    commandType: CommandType.StoredProcedure);

// Dynamic
DynamicParameters parameter = new DynamicParameters();

parameter.Add("@Kind", InvoiceKind.WebInvoice, DbType.Int32, ParameterDirection.Input);
parameter.Add("@Code", "Many_Insert_0", DbType.String, ParameterDirection.Input);
parameter.Add("@RowCount", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

connection.Execute(sql,
    parameter,
    commandType: CommandType.StoredProcedure);

int rowCount = parameter.Get<int>("@RowCount");

// List
connection.Query<Invoice>(sql, new {Kind = new[] {InvoiceKind.StoreInvoice, InvoiceKind.WebInvoice}}).ToList();
// String
connection.Query<Invoice>(sql, new {Code = new DbString {Value = "Invoice_1", IsFixedLength = false, Length = 9, IsAnsi = true}}).ToList();

Result

When using Dapper, you can map your query results to objects in several ways. The result returned by the queries method can be mapped to multiple types:

  • Anonymous: Allow you to store the results of a SQL query in an anonymous type.
  • Strongly Typed: Allow you to store the results of a SQL query in a strongly typed manner.
  • Multi-Mapping: Map the result to a strongly typed list with relations.
  • Multi-Result: Execute multiple queries within the same command and map results.
  • Multi-Type: Execute a query and map the result to a list of different types.
string sqlOrderDetails = "SELECT TOP 10 * FROM OrderDetails;";

using (var connection = new SqlConnection(FiddleHelper.GetConnectionStringSqlServerW3Schools()))
{
    var anonymousList = connection.Query(sqlOrderDetails).ToList();
    var orderDetails = connection.Query<OrderDetail>(sqlOrderDetails).ToList();

    Console.WriteLine(anonymousList.Count);
    Console.WriteLine(orderDetails.Count);

    FiddleHelper.WriteTable(orderDetails);

    FiddleHelper.WriteTable(connection.Query(sqlOrderDetails).FirstOrDefault());
}

Try it: .NET Core | .NET Framework

Utilities

In addition, to the ability to execute multiple statements in a single round trip to the server, Dapper also provides some additional functionalities that can greatly improve performance in some scenarios.

  • Async: Dapper also provides an Async (asynchronous) version of extension methods
  • Buffered: A buffered query return the entire reader at once
  • Transaction: Support the transaction and TransactionScope
  • Stored Procedure: Has built-in support for caching stored procedures.
// Async
connection.QueryAsync<Invoice>(sql)

// Buffered
connection.Query<Invoice>(sql, buffered: false)

// Transaction
using (var transaction = connection.BeginTransaction())
{
    var affectedRows = connection.Execute(sql,
    new {Kind = InvoiceKind.WebInvoice, Code = "Single_Insert_1"},
    commandType: CommandType.StoredProcedure,
    transaction: transaction);

    transaction.Commit();
}

// Stored Procedure
var affectedRows = connection.Execute(sql,
new {Kind = InvoiceKind.WebInvoice, Code = "Single_Insert_1"},
commandType: CommandType.StoredProcedure);