Skip to main content

Decision guide

Dapper ecosystem packages

Dapper keeps data access close to SQL and is often chosen for read-heavy or performance-critical paths. The secondary decision is how much convenience to add around core Dapper without hiding query intent or creating fragile conventions.

5 criteria3 packages5-point checklist

The decision to make

Should a .NET data layer use raw Dapper only or include Dapper extension packages?

  • Need for explicit SQL control versus convention-driven CRUD helpers.
  • Mapping complexity for multi-mapping, one-to-many hydration and custom type handlers.
  • Balance between low abstraction overhead and team productivity.
  • Transaction management, batching and provider portability requirements.
  • How much generated SQL you are willing to review and test explicitly.

Shortlist and trade-offs

These options are starting points, not an exhaustive market list. Verify the current release, compatibility, license and advisory information for your project on the linked package pages.

1

Dapper

Core micro-ORM focused on fast materialization and minimal abstraction over SQL.

Inspect package
Best fit
Teams that want explicit SQL ownership, predictable query plans and thin data access layers.
Validate first
You must own SQL composition, migration strategy and relational modeling discipline yourself.
2

Dapper.Contrib

Adds simple CRUD helpers and attribute-based mapping conventions on top of Dapper.

Inspect package
Best fit
Internal services with straightforward entity CRUD where convenience outweighs advanced SQL control.
Validate first
Generic convenience APIs can become limiting for complex joins, projections or provider-specific SQL.
3

Dommel

Convention-based CRUD and expression support for Dapper-oriented repositories.

Inspect package
Best fit
Projects that want more repository ergonomics while still staying in the Dapper ecosystem.
Validate first
Convention assumptions and SQL generation should be validated against indexing and execution plans.

Practical implementation plan

  1. 1Keep SQL close to the feature that owns it and parameterize every value. Define small request/response records instead of mapping whole persistence entities by default.
  2. 2Open connections late and dispose them predictably; pass cancellation tokens through async calls. Use explicit transactions only for a clearly defined atomic boundary.
  3. 3Treat query plans as part of the implementation. Add indexes for measured access patterns, set command timeouts deliberately, and test mappings against the actual provider.

Common pitfalls

  • Building SQL with interpolation or concatenation instead of parameters, which creates injection risk and fragments database plan caches.
  • Hiding complex queries behind generic repositories until the SQL, transaction scope, and performance characteristics are impossible to see.
  • Assuming multi-mapping automatically resolves aggregates correctly; verify split columns and de-duplicate parent rows explicitly.

Before production

  • All external values are bound as parameters, including filters and paging values.
  • Queries have cancellation, timeout, and error logging behavior appropriate to the request path.
  • Migration and schema ownership are explicit even though Dapper does not provide them.
  • High-volume queries have representative integration tests and execution-plan review.
  • Connection strings and database credentials use the deployment platform's secret store.

When to revisit this choice

Revisit your Dapper package mix when domain queries become more complex, write models grow, or query-generation conventions hide critical SQL details.

Data, method and limits

Sources: the public NuGet v3 registry and NuBrowse editorial review. Refresh: package pages read current registry metadata when viewed; guide text is revised separately. Method: the shortlist favours distinct use cases and spells out trade-offs instead of calculating a quality score. Limit: validate the specific version, license, framework and operational requirements in your project.