Overview
Savvyio.Extensions.DependencyInjection.DapperExtensions registers DapperExtensions-backed persistent data stores with Microsoft Dependency Injection. It adds IServiceCollection extension methods for wiring Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore<T> into the Savvy I/O data store abstractions, and it includes a marker-aware store type for scenarios where the same application needs more than one implementation for the same DTO.
The package is intentionally narrow. CRUD and query behavior remain in Savvyio.Extensions.DapperExtensions, while this package contributes the DI registration surface and the IDapperDataSource<TMarker> adapter needed to bind a store to the correct marked data source.
Key APIs
AddDapperExtensionsDataStore<T> registers DapperExtensionsDataStore<T> in an IServiceCollection by forwarding it to the Savvy I/O persistent data store abstractions with DapperExtensionsQueryOptions<T> as the options type. The package tests show that separate DTO types can be registered side by side and resolved through IPersistentDataStore<T, DapperExtensionsQueryOptions<T>>.
AddDapperExtensionsDataStore<T, TMarker> registers a DapperExtensions-backed store with a marker type so DI can distinguish multiple implementations for the same DTO. The tests resolve separate IPersistentDataStore<T, DapperExtensionsQueryOptions<T>, TMarker> services for two markers and verify that each registration yields a distinct store instance.
DapperExtensionsDataStore<T, TMarker> is the marker-aware store type added by this package. It derives from Savvyio.Extensions.DapperExtensions.DapperExtensionsDataStore<T>, implements IPersistentDataStore<T, DapperExtensionsQueryOptions<T>, TMarker>, and changes the constructor dependency to IDapperDataSource<TMarker> so the container can bind it to the matching marked data source.
Basic usage
using System;
using System.Data;
using Codebelt.Extensions.Xunit;
using Microsoft.Extensions.DependencyInjection;
using Savvyio.Extensions.DapperExtensions;
using Savvyio.Extensions.DependencyInjection.Dapper;
using Savvyio.Extensions.DependencyInjection.DapperExtensions;
using Savvyio.Extensions.DependencyInjection.Data;
using Xunit;
namespace MyProject.Tests;
public class DapperExtensionsRegistrationTests : Test
{
public DapperExtensionsRegistrationTests(ITestOutputHelper output) : base(output) { }
[Fact]
public void AddDapperExtensionsDataStore_MarkerServices_RegistersDescriptors()
{
var services = new ServiceCollection();
services.AddDapperDataSource<OrdersDb>(o => o.ConnectionFactory = () => new InertDbConnection());
services.AddDapperExtensionsDataStore<AccountRecord, OrdersDb>();
services.AddDapperDataSource<ReportingDb>(o => o.ConnectionFactory = () => new InertDbConnection());
services.AddDapperExtensionsDataStore<AccountRecord, ReportingDb>();
using var provider = services.BuildServiceProvider();
var ordersStore = provider.GetRequiredService<IPersistentDataStore<AccountRecord, DapperExtensionsQueryOptions<AccountRecord>, OrdersDb>>();
var reportingStore = provider.GetRequiredService<IPersistentDataStore<AccountRecord, DapperExtensionsQueryOptions<AccountRecord>, ReportingDb>>();
TestOutput.WriteLine($"Resolved stores: {ordersStore.GetType().Name}, {reportingStore.GetType().Name}");
Assert.IsType<DapperExtensionsDataStore<AccountRecord, OrdersDb>>(ordersStore);
Assert.IsType<DapperExtensionsDataStore<AccountRecord, ReportingDb>>(reportingStore);
Assert.NotSame(ordersStore, reportingStore);
}
private sealed class AccountRecord { }
private sealed class OrdersDb { }
private sealed class ReportingDb { }
private sealed class InertDbConnection : IDbConnection
{
public string ConnectionString { get; set; } = "inert";
public int ConnectionTimeout => 0;
public string Database => "inert";
public ConnectionState State { get; private set; }
public IDbTransaction BeginTransaction() => throw new NotSupportedException();
public IDbTransaction BeginTransaction(IsolationLevel il) => throw new NotSupportedException();
public void ChangeDatabase(string databaseName) { }
public void Close() => State = ConnectionState.Closed;
public IDbCommand CreateCommand() => throw new NotSupportedException();
public void Open() => State = ConnectionState.Open;
public void Dispose() => Close();
}
}
Use this pattern when the same DTO type must resolve against more than one Dapper-backed source in the same service provider. The marker-aware overload keeps each IPersistentDataStore registration distinct so consumers can request the correct store by marker type.
Installation
dotnet add package Savvyio.Extensions.DependencyInjection.DapperExtensions
Usage guidance
Adopt this package when you already use Microsoft.Extensions.DependencyInjection and want DapperExtensions-backed stores to participate in Savvy I/O's DI abstractions, especially when marker types are needed to separate multiple registrations. Choose Savvyio.Extensions.DapperExtensions when you only need the store implementation itself, or Savvyio.Extensions.DependencyInjection.Dapper when you only need to register Dapper data sources without the DapperExtensions store layer.
Family packages
- 🏭Savvyio.App
- 📦Savvyio.Commands
- 📦Savvyio.Commands.Messaging
- 📦Savvyio.Core
- 📦Savvyio.Domain
- 📦Savvyio.Domain.EventSourcing
- 📦Savvyio.EventDriven
- 📦Savvyio.EventDriven.Messaging
- 📦Savvyio.Extensions.Dapper
- 📦Savvyio.Extensions.DapperExtensions
- 📦Savvyio.Extensions.DependencyInjection
- 📦Savvyio.Extensions.DependencyInjection.Dapper
- 📦Savvyio.Extensions.DependencyInjection.Domain
- 📦Savvyio.Extensions.DependencyInjection.EFCore
- 📦Savvyio.Extensions.DependencyInjection.EFCore.Domain
- 📦Savvyio.Extensions.DependencyInjection.EFCore.Domain.EventSourcing
- 📦Savvyio.Extensions.DependencyInjection.NATS
- 📝Savvyio.Extensions.DependencyInjection.Newtonsoft.Json
- 📦Savvyio.Extensions.DependencyInjection.QueueStorage
- 📦Savvyio.Extensions.DependencyInjection.RabbitMQ
- 📦Savvyio.Extensions.DependencyInjection.SimpleQueueService
- 📝Savvyio.Extensions.DependencyInjection.Text.Json
- 📦Savvyio.Extensions.Dispatchers
- 📦Savvyio.Extensions.EFCore
- 📦Savvyio.Extensions.EFCore.Domain
- 📦Savvyio.Extensions.EFCore.Domain.EventSourcing
- 📦Savvyio.Extensions.NATS
- 📝Savvyio.Extensions.Newtonsoft.Json
- 📦Savvyio.Extensions.QueueStorage
- 📦Savvyio.Extensions.RabbitMQ
- 📦Savvyio.Extensions.SimpleQueueService
- 📝Savvyio.Extensions.Text.Json
- 📦Savvyio.Messaging
- 📦Savvyio.Queries