Dommel 3.3.1

dotnet add package Dommel --version 3.3.1
NuGet\Install-Package Dommel -Version 3.3.1
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Dommel" Version="3.3.1" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Dommel --version 3.3.1
#r "nuget: Dommel, 3.3.1"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Dommel as a Cake Addin
#addin nuget:?package=Dommel&version=3.3.1

// Install Dommel as a Cake Tool
#tool nuget:?package=Dommel&version=3.3.1

Dommel

CRUD operations with Dapper made simple.

Windows Linux NuGet MyGet Test Coverage
AppVeyor Travis NuGet MyGet Pre Release codecov

<hr>

Dommel provides a convenient API for CRUD operations using extension methods on the IDbConnection interface. The SQL queries are generated based on your POCO entities. Dommel also supports LINQ expressions which are being translated to SQL expressions. Dapper is used for query execution and object mapping.

There are several extensibility points available to change the behavior of resolving table names, column names, the key property and POCO properties. See Extensibility for more details.

Installing Dommel

Dommel is available on NuGet.

Install using the .NET CLI:

dotnet add package Dommel

Install using the NuGet Package Manager:

Install-Package Dommel

Using Dommel

Retrieving entities by ID

var product = await connection.GetAsync<Product>(1);

Retrieving all entities in a table

var products = await connection.GetAllAsync<Product>();

Selecting entities using a predicate

Dommel allows you to specify a predicate which is being translated into a SQL expression. The arguments in the lambda expression are added as parameters to the command.

var products = await connection.SelectAsync<Product>(p => p.Name == "Awesome bike" && p.Created < new DateTime(2014, 12, 31) && p.InStock > 5);

Which would translate in the following SQL:

select * from Products where Name = @p1 and Created < @p2 and InStock > @p3

You can add parentheses to combine and & or queries:

var products = await connection.SelectAsync<Product>(p => p.Name == "Awesome bike" && (p.Created < new DateTime(2014, 12, 31) || p.InStock > 5));

Which would translate in the following SQL:

select * from Products where Name = @p1 and (Created < @p2 or InStock > @p3)

There is also a FirstOrDefaultAsync<T>(...) method available to select the first entity matching the predicate.

Like-queries

It is possible to generate LIKE-queries using Contains(), StartsWith() or EndsWith() on string properties:

var products = await connection.SelectAsync<Product>(p => p.Name.Contains("bike"));
var products = await connection.SelectAsync<Product>(p => p.Name.StartsWith("bike"));
var products = await connection.SelectAsync<Product>(p => p.Name.EndsWith("bike"));

Inserting entities

var product = new Product { Name = "Awesome bike", InStock = 4 };
var id = await connection.InsertAsync(product);

Updating entities

var product = await connection.GetAsync<Product>(1);
product.Name = "New name";
await connection.UpdateAsync(product);

Removing entities

var product = await connection.GetAsync<Product>(1);
await connection.DeleteAsync(product);

Multi mapping

One-to-one relations

Dommel is able to generate join-queries based on the specified multi mapping function. Consider the following POCO's:

public class Product
{
    public int Id { get; set; }

    public string Name { get; set; }

    // Maps to the foreign key column
    public int CategoryId { get; set; }

    // The navigation property
    public Category Category { get; set; }
}


public class Category
{
    public int Id { get; set; }

    public string Name { get; set; }
}

The Product with its associated Category can be queried toegether using the Get<T1, T2, ..., TResult>() method:

var product = await product.GetAsync<Product, Category, Product>(1, (product, category) =>
{
    product.Category = category;
    return product;
});
Foreign key columns

CategoryId is automatically used as foreign key between Product and Category. This follows a simple convention: joining table name + Id (Category + Id). You can override this behavior by using the [ForeignKey("ForeignKeyColumnName")] attribute or by implementing your own IForeignKeyPropertyResolver.

One-to-many relations

One-to-many relationships work in a similar way, expect that the foreign key is defined on the joined type rather than the source type. For example:

public class Order
{
    public int Id { get; set; }

    // The navigation property
    public ICollection<OrderLine> OrderLines { get; set; } = new List<OrderLine>();
}

public class OrderLine
{
    public int Id { get; set; }

    // The foreign key column to the Order table
    public int OrderId { get; set; }

    public string Description { get; set; }
}

The Order with its child OrderLine's can be queried toegether using the Get<T1, T2, ..., TResult>() method:

var product = await product.GetAsync<Order, OrderLine, Order>(1, (order, line) =>
{
    // Naive mapping example, in reality it requires more gymnastics
    order.OrderLines.Add(line);
    return order;
});

Automatic multi mapping

Note: this is an experimental feature.

Dommel is able to create simple join-expressions for retrieving parent-child entities. One-to-one and one-to-many relations are supported. It works the samy way as regular mapping, except there is no need to specify a function which performs the mapping of the objects. Using the same POCO's as the previous examples:

Retrieving a Product and its associated Category:

var product = product.Get<Product, Category, Product>(1);

Retrieving one Order and with its child OrderLine's:

var product = product.Get<Order, OrderLine, Order>(1);
Entity equality

When joining with two or more tables with a one-to-many relationship, you are required to override Equals(object obj) method or implement the IEquatable<T> interface on your POCO's so Dommel can determine whether an entity is already added to the collection. For example:

public class OrderLine : IEquatable<OrderLine>
{
    public int Id { get; set; }

    public int OrderId { get; set; }

    public string Description { get; set; }

    public bool Equals(OrderLine other) => Id == other.Id;
}

Combining Select and multi-mapping

It's possible to combine Select queries and multi-mapping. For example:

var products = await connection.SelectAsync<Product, Category, Product>(x => x.Name.StartsWith("bike"));

This is applicable for Select, SelectAsync, FirstOrDefault and FirstOrDefaultAsync. Both with manual and automatic multi-mapping.

From-queries

With From-queries you can create more complex queries on a certain table by providing access to the SqlExpression<T>. For example:

var products = await connection.FromAsync<Product>(sql => sql
    .Where(x => x.Name.StartsWith("bike") && x.DeletedOn == null)
    .OrWhere(x => x.InStock > 5)
    .OrderBy(x => x.DateCreated)
    .Page(1, 25)
    .Select()));

Async and non-async

All Dommel methods have async and non-async variants, such as as Get & GetAsync, GetAll & GetAllAsync, Select & SelectAsync, Insert & InsertAsync, Update & UpdateAsync, Delete & DeleteAsync, etc.

Query builders

Dommel supports building specialized queries for a certain RDBMS. By default, query builders for the following RDMBS are included: SQL Server, SQL Server CE, SQLite, MySQL and Postgres. The query builder to be used is determined by the connection type. To add or overwrite an existing query builder, use the AddSqlBuilder() method:

DommelMapper.AddSqlBuilder(typeof(SqlConnection), new CustomSqlBuilder());

<hr>

Extensibility

ITableNameResolver

Implement this interface if you want to customize the resolving of table names when building SQL queries.

public class CustomTableNameResolver : ITableNameResolver
{
    public string ResolveTableName(Type type)
    {
        // Every table has prefix 'tbl'.
        return $"tbl{type.Name}";
    }
}

Use the SetTableNameResolver() method to register the custom implementation:

SetTableNameResolver(new CustomTableNameResolver());
IKeyPropertyResolver

Implement this interface if you want to customize the resolving of the key property of an entity. By default, Dommel will search for a property with the [Key] attribute, or a column with the name 'Id'.

If you, for example, have the naming convention of {TypeName}Id for key properties, you would implement the IKeyPropertyResolver like this:

public class CustomKeyPropertyResolver : IKeyPropertyResolver
{
    public ColumnPropertyInfo[] ResolveKeyProperties(Type type)
    {
        return new [] { new ColumnPropertyInfo(type.GetProperties().Single(p => p.Name == $"{type.Name}Id"), isKey: true) };
    }
}

Use the SetKeyPropertyResolver() method to register the custom implementation:

DommelMapper.SetKeyPropertyResolver(new CustomKeyPropertyResolver());
IForeignKeyPropertyResolver

Implement this interface if you want to customize the resolving of the foreign key property from one entity to another. By default Dommel will search for a property of {TypeName}Id or the column name specified using the [ForeignKey] attribute.

This is a rather advanced interface. Providing your own implementation requires quite some knowledge of the way Dommel handles foreign key relationships. Consider subclassing DefaultForeignKeyPropertyResolver and override ResolveForeignKeyProperty().

Use the SetForeignKeyPropertyResolver() method to register the custom implementation:

DommelMapper.SetForeignKeyPropertyResolver(new CustomForeignKeyPropertyResolver());
IColumnNameResolver

Implement this interface if you want to customize the resolving of column names for when building SQL queries. This is useful when your naming conventions for database columns are different than your POCO properties.

public class CustomColumnNameResolver : IColumnNameResolver
{
    public string ResolveColumnName(PropertyInfo propertyInfo)
    {
        // Every column has prefix 'fld' and is uppercase.
        return $"fld{propertyInfo.Name.ToUpper()}";
    }
}

Use the SetColumnNameResolver() method to register the custom implementation:

DommelMapper.SetColumnNameResolver(new CustomColumnNameResolver());
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (19)

Showing the top 5 NuGet packages that depend on Dommel:

Package Downloads
Dapper.FluentMap.Dommel

Dapper.FluentMap extension for Dommel support.

ZKWeb.ORM.Dapper

Support use Dapper in ZKWeb. For more information please visit project site.

Dommel.Json

JSON support for Dommel.

Webenable.FeatureToggles

Simple feature toggles implementation for ASP.NET Core.

RCommon.Persistence.Dapper

A cohesive set of .NET 7 infrastructure libraries that utilizes abstractions for persistence, unit of work/transactions, distributed events, distributed transactions, and more.

GitHub repositories (2)

Showing the top 2 popular GitHub repositories that depend on Dommel:

Repository Stars
zkweb-framework/ZKWeb
A flexible web framework supports .Net Framework and .Net Core
henkmollema/Dapper-FluentMap
Provides a simple API to fluently map POCO properties to database columns when using Dapper.
Version Downloads Last updated
3.3.1 730 4/4/2024
3.3.0 16,250 1/18/2024
3.2.1 3,498 1/17/2024
3.2.0 9,656 11/15/2023
3.1.0 35,457 8/7/2023
3.0.0 213,722 12/21/2021
2.4.0 4,432 12/2/2021
2.3.3 20,966 11/4/2021
2.3.2 153,032 7/12/2021
2.2.0 54,886 3/31/2021
2.1.0 115,757 9/8/2020
2.0.0 505,273 6/10/2020
1.11.0 476,406 3/28/2019
1.10.1 133,940 3/7/2018
1.9.0 166,632 8/18/2017
1.8.1 17,366 3/22/2017
1.8.0 18,513 1/16/2017
1.7.3 3,393 12/6/2016
1.7.2 3,564 11/18/2016
1.7.1 5,901 9/14/2016
1.7.0 2,578 9/6/2016
1.6.1 25,485 7/7/2016
1.6.0 5,000 6/10/2016
1.5.0 2,583 2/29/2016
1.4.2 8,137 8/24/2015
1.4.1 2,525 8/22/2015
1.4.0 2,595 5/29/2015
1.3.4 11,289 3/1/2016
1.3.3 3,777 3/12/2015
1.3.2 2,588 3/12/2015
1.3.1 2,733 2/9/2015
1.3.0 3,016 12/4/2014
1.2.0 2,503 9/29/2014
1.1.0 2,872 7/3/2014
1.0.0 3,170 6/23/2014