This file provides guidance to coding agents (Claude Code, GitHub Copilot, etc.) when working with code in this repository.
# Build
dotnet build Dommel.sln -c Release
# Run all unit tests (no database required)
dotnet test test/Dommel.Tests
# Run all integration tests (requires local SQL Server, MySQL, PostgreSQL)
dotnet test test/Dommel.IntegrationTests
# Run a single test by name
dotnet test test/Dommel.Tests --filter "FullyQualifiedName~CountTests.BuildCountAllSql"
# Full CI build (restore, build, test all four projects, coverage, pack)
./build.ps1The four test projects are Dommel.Tests, Dommel.IntegrationTests, Dommel.Json.Tests, and Dommel.Json.IntegrationTests.
Dommel is a Dapper extension library that generates CRUD SQL from POCO entities via IDbConnection extension methods. Dapper handles query execution and object mapping.
DommelMapper is a single static partial class split across many files in src/Dommel/ — one per CRUD concern (Get.cs, Insert.cs, Update.cs, Delete.cs, Select.cs, Count.cs, Any.cs, From.cs, Project.cs, Scalar.cs, plus multi-map files). Each file adds extension methods to IDbConnection.
Core flow for every CRUD operation:
- Extension method receives
IDbConnection(+ optionalIDbTransaction,CancellationToken) - Calls an
internal static Build*Query()method that checksQueryCache(aConcurrentDictionary<QueryCacheKey, string>, seeCache.cs) - On cache miss: uses
Resolversto resolve table names, column names, and key properties, then builds the SQL string - Delegates to Dapper for execution and mapping
Key collaborators:
ISqlBuilder— Abstraction for DB-specific SQL (identifier quoting, insert-ID retrieval, paging, LIKE). Implementations:SqlServerSqlBuilder,MySqlSqlBuilder,PostgresSqlBuilder,SqliteSqlBuilder,SqlServerCeSqlBuilder. Looked up byconnection.GetType().Name(lowercase) in a dictionary; register new ones viaDommelMapper.AddSqlBuilder().Resolvers— Static caching layer (ConcurrentDictionary) over the resolver interfaces (ITableNameResolver,IColumnNameResolver,IKeyPropertyResolver,IPropertyResolver,IForeignKeyPropertyResolver). All replaceable viaDommelMapper.SetTableNameResolver()etc. New resolvers must be idempotent since results are cached.SqlExpression<T>— Translates LINQExpression<Func<T, bool>>to SQL WHERE clauses with auto-numbered parameters (@p1,@p2). Designed for subclassing (virtual methods).
Dommel.Json (src/Dommel.Json/) is a companion package adding JSON column support. It replaces all SQL builders with JSON-aware variants (implementing IJsonSqlBuilder), swaps the SqlExpressionFactory to produce JsonSqlExpression<T> (which overrides VisitMemberAccess to emit DB-specific JSON path queries), and registers Dapper type handlers for [JsonData]-annotated properties.
-
Extension method pattern: Every public API method is an
IDbConnectionextension method on theDommelMapperpartial class, with a sync and an async variant. The async variant accepts an optionalCancellationToken;IDbTransaction? transaction = nullis a standard parameter. -
Entity mapping attributes:
[Key]or a property namedId— marks the key property (defaults toDatabaseGeneratedOption.Identity)[DatabaseGenerated]— controls identity/computed/none behavior[Table]/[Column]— custom name mapping (fromSystem.ComponentModel.DataAnnotations.Schema)[Ignore](Dommel's own,IgnoreAttribute.cs) or[NotMapped]— exclude property from mapping[ForeignKey]— navigation property resolution for multi-map queries
-
Target frameworks: Libraries multi-target
netstandard2.0,net8.0,net9.0,net10.0. Test projects targetnet10.0only. Nullable reference types are enabled project-wide viaDirectory.Build.props; the package version is set there (VersionPrefix).
- Unit tests (
Dommel.Tests,Dommel.Json.Tests): Callinternal static Build*methods directly, passing a concreteISqlBuilder, and assert on the generated SQL string. Test model classes are inline or inModels.cs. Framework is xUnit. - Integration tests (
Dommel.IntegrationTests,Dommel.Json.IntegrationTests): Use[Theory]+[ClassData(typeof(DatabaseTestData))]to run each test against all configured database drivers (SQL Server, MySQL, PostgreSQL). Tests share aDatabaseFixturevia xUnit[Collection("Database")]that handles DB setup/seeding.