DMany 1.0.4
dotnet add package DMany --version 1.0.4
NuGet\Install-Package DMany -Version 1.0.4
<PackageReference Include="DMany" Version="1.0.4" />
<PackageVersion Include="DMany" Version="1.0.4" />
<PackageReference Include="DMany" />
paket add DMany --version 1.0.4
#r "nuget: DMany, 1.0.4"
#:package DMany@1.0.4
#addin nuget:?package=DMany&version=1.0.4
#tool nuget:?package=DMany&version=1.0.4
DapperMany
Bulk operations for Dapper: fast InsertMany, InsertManyGraph, UpdateMany and DeleteMany across SQL Server, PostgreSQL and MySQL.
Table of Contents
- Overview: What DapperMany is and when to use it.
- Installation: How to add the package or build from source.
- Quick Start: Minimal examples (InsertMany, InsertManyGraph, UpdateMany, DeleteMany).
- Mapping Attributes:
[Table],[Key],[DatabaseGenerated],[HasMany]. - Docker local setup: Run database stack and connection strings.
- Providers: Provider-specific notes (SQL Server, PostgreSQL, MySQL).
- Running samples and tests: Commands to run the shipped samples and integration tests.
- Contributing & License
Overview
DapperMany provides a small set of extension methods over IDbConnection to perform bulk-style operations with minimal SQL authoring. It aims to keep an API surface small and predictable while supporting provider-specific optimizations (bulk copy strategies) under the hood.
Supported operations (public API):
InsertManyAsync<T>(this IDbConnection connection, IEnumerable<T> entities, ...)— inserts a flat collection or entity graph with auto-detectionUpdateManyAsync<T>(this IDbConnection connection, IEnumerable<T> entities, ...)DeleteManyAsync<T>(this IDbConnection connection, IEnumerable<T> entities, ...)
See implementation: src/DapperMany/DapperManyExtensions.cs
Installation
Prefer installing the published package when available:
dotnet add package DMany
dotnet add package DMany.MySQL
dotnet add package DMany.Postgres
dotnet add package DMany.SqlServer
Or build from source and reference the project directly:
dotnet restore
dotnet build DapperMany.sln -c Release
Quick Start
Below are short examples extracted from the samples project.
Model definitions (attributes)
Example Pedido (parent) and ItemPedido (child): see samples/DapperMany.Samples/Models/Pedido.cs and samples/DapperMany.Samples/Models/ItemPedido.cs
[Table("Pedidos")]
public class Pedido
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public required string NumeroDocumento { get; set; }
public DateTime DataPedido { get; set; }
public decimal ValorTotal { get; set; }
public string Status { get; set; } = "Pendente";
[HasMany(nameof(ItemPedido.PedidoId))]
public List<ItemPedido> Itens { get; set; } = new();
}
InsertMany (simple list)
var orders = new List<Pedido>
{
new Pedido { NumeroDocumento = "PED-001", DataPedido = DateTime.UtcNow, ValorTotal = 1500.00m },
new Pedido { NumeroDocumento = "PED-002", ValorTotal = 2500.00m }
};
var rowsInserted = await connection.InsertManyAsync(orders);
Console.WriteLine($"Inserted {rowsInserted} order(s)");
Snippet source: samples/DapperMany.Samples/Program.cs
InsertManyGraph (parents + children)
var orders = new List<Pedido>
{
new Pedido
{
NumeroDocumento = "PED-GRAPH-001",
ValorTotal = 1200.00m,
Itens = new()
{
new ItemPedido { Descricao = "Laptop", Quantidade = 1, ValorUnitario = 800m },
new ItemPedido { Descricao = "Mouse", Quantidade = 2, ValorUnitario = 50m }
}
}
};
int insertedCount = await connection.InsertManyAsync(orders);
// Parent IDs and children FK values are populated by the library automatically
Snippet source: samples/DapperMany.Samples/Program.cs
UpdateMany
var existingOrders = connection.Query<Pedido>(
"SELECT TOP 3 * FROM Pedidos ORDER BY Id DESC").ToList();
foreach (var order in existingOrders)
order.Status = "Processado";
var updatedCount = await connection.UpdateManyAsync(existingOrders);
Console.WriteLine($"Updated {updatedCount} orders");
Snippet source: samples/DapperMany.Samples/Program.cs
DeleteMany
var ordersToDelete = connection.Query<Pedido>(
"SELECT TOP 2 * FROM Pedidos ORDER BY Id ASC").ToList();
var deleteCount = await connection.DeleteManyAsync(ordersToDelete);
Console.WriteLine($"Deleted {deleteCount} orders");
Snippet source: samples/DapperMany.Samples/Program.cs
Composite Key Support
DapperMany supports multi-column primary keys, enabling use cases like multi-tenancy where entities are uniquely identified by multiple columns.
Model with Composite Key
[Table("TenantPedidos")]
public class TenantPedido
{
// First key: Tenant identifier
[Key]
public required string TenantId { get; set; }
// Second key: Document number (unique per tenant)
[Key]
public required string DocumentNumber { get; set; }
public DateTime OrderDate { get; set; } = DateTime.UtcNow;
public decimal TotalAmount { get; set; }
public string Status { get; set; } = "Pendente";
}
Using Composite Keys
All bulk operations work seamlessly with composite keys. UpdateMany and DeleteMany use all key columns in the WHERE clause:
// Insert multiple tenant orders
var orders = new List<TenantPedido>
{
new TenantPedido { TenantId = "TENANT_A", DocumentNumber = "DOC001", TotalAmount = 1000m },
new TenantPedido { TenantId = "TENANT_A", DocumentNumber = "DOC002", TotalAmount = 2000m },
new TenantPedido { TenantId = "TENANT_B", DocumentNumber = "DOC001", TotalAmount = 1500m }
};
var inserted = await connection.InsertManyAsync(orders);
// Update orders
orders[0].Status = "Processado";
var updated = await connection.UpdateManyAsync(new[] { orders[0] });
// Generated WHERE: TenantId = @key0 AND DocumentNumber = @key1
// Delete orders by passing entity objects
var deleted = await connection.DeleteManyAsync(new[] { orders[0], orders[2] });
// Generated WHERE: (TenantId = @k0_0 AND DocumentNumber = @k0_1)
// OR (TenantId = @k1_0 AND DocumentNumber = @k1_1)
Composite Key Constraints
- At least one
[Key]attribute is required. - Composite keys cannot use
[DatabaseGenerated(Identity)](auto-increment only works with single keys). - Key properties are ordered alphabetically for deterministic SQL generation.
All database providers (SQL Server, PostgreSQL, MySQL) generate correct SQL syntax automatically.
See implementation: tests/DapperMany.SqlServer.IntegrationTests/CompositeKeyIntegrationTests.cs
Mapping Attributes
[Table("Name")]— maps a CLR class to a DB table.[Key]— marks the primary key property.[DatabaseGenerated(DatabaseGeneratedOption.Identity)]— identity/auto-increment.[HasMany("ForeignKeyName")]— declares a 1:N collection and allowsInsertManyGraphto populate child FKs.
See definitions: src/DapperMany/Attributes
Docker local setup
A docker compose file that brings up SQL Server, PostgreSQL and MySQL is included under docker/.
# start databases
docker compose -f docker/docker-compose.yml up -d
# stop and remove
docker compose -f docker/docker-compose.yml down
Default connection strings (sample project):
{
"ConnectionStrings": {
"SqlServer": "Server=localhost,1433;Initial Catalog=DapperMany;User Id=sa;Password=SqlServer123!;Encrypt=false;",
"PostgreSQL": "Host=localhost;Port=5432;Database=dappermany;Username=postgres;Password=Postgres123!;",
"MySQL": "Server=localhost;Port=3306;Database=dappermany;Uid=root;Pwd=MySql123!;"
}
}
DB schema initialization scripts are located at:
- docker/sqlserver/init/01-schema.sql
- docker/postgres/init/01-schema.sql
- docker/mysql/init/01-schema.sql
Providers
Provider-specific optimizations are implemented under src/:
- src/DapperMany.SqlServer/SqlServerBulkCopyStrategy.cs
- src/DapperMany.Postgres/PostgreSqlBulkCopyStrategy.cs
- src/DapperMany.MySql/MySqlBulkCopyStrategy.cs
Provider notes and design decisions are recorded in specs/spec.md
Diagnostics
In Debug builds the library emits lightweight diagnostics for bulk operations to the debug output using System.Diagnostics.Debug.WriteLine() along with a Stopwatch measurement. Messages follow the format:
[DAPPERMANY] <Op> <Entity> (<Provider>): affected=<N>, elapsed=<Tms>ms
These logs are produced only in #if DEBUG builds and are intended for local troubleshooting. They are emitted by provider implementations and the graph orchestrator (not by public extension methods).
Running the samples and tests
Make sure Docker is running the local DBs before executing integration tests or the sample project.
docker compose -f docker/docker-compose.yml up -d
dotnet restore
dotnet build DapperMany.sln -c Release
dotnet run --project samples/DapperMany.Samples
# to run a specific integration test project (SQL Server tests require a running SQL Server)
dotnet test tests/DapperMany.SqlServer.IntegrationTests -c Release
Integration tests
Integration tests live under tests/ and validate InsertManyGraph, UpdateMany and DeleteMany behavior. Example:
Contributing
- Fork, create a feature branch, open a PR.
- Run unit tests:
dotnet test tests/DapperMany.UnitTests.
License
This repository is licensed under the terms in LICENSE.
If you'd like, I can now:
- Run
dotnet buildanddotnet testlocally to verify the repository builds and that the README snippets compile. (Requires Docker for integration tests.) - Open a follow-up PR with the README and small edits to
docker/README.md.
Pick one and I'll proceed.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- Dapper (>= 2.0.123)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on DMany:
| Package | Downloads |
|---|---|
|
DMany.SqlServer
High-performance bulk operations framework extending Dapper with InsertMany, UpdateMany, DeleteMany |
|
|
DMany.Postgres
High-performance bulk operations framework extending Dapper with InsertMany, UpdateMany, DeleteMany |
|
|
DMany.MySql
High-performance bulk operations framework extending Dapper with InsertMany, UpdateMany, DeleteMany |
GitHub repositories
This package is not used by any popular GitHub repositories.