A collection of utilities for working with persistence in .NET using Dapper.
Factory implementations for MySql, MsSql and SQLite connections implementing an IConnectionFactory
interface which expose the following methods:
Task<IDbConnection> GetAsync(CancellationToken cancellationToken = default);
Task<IDbConnection> GetAsync(string configKey, CancellationToken cancellationToken = default);
They are designed to be used with dependency injection taking a Microsoft.Extensions.Configuration.IConfiguration
object which provides access to connection string configuration. When getting connections you have the options to use a configuration key with section support e.g. ImportantStrings:BestConnectionEver
or not which will default to using ConnectionStrings:DefaultConnection
.
The factories are implemented using the following data providers:
Connection type | Data provider |
---|---|
MsSql | Microsoft.Data.SqlClient |
MySql | MySql.Data |
SQLite | Microsoft.Data.Sqlite |
Intended to be used for testing the In-memory database is built with SQLite and the factory class differs slightly from the others. It implements another interface IInMemoryConnectionFactory
which extends IDisposable
and exposes a single method:
Task<SqliteConnection> GetAsync(CancellationToken cancellationToken = default);
Here an actual SqliteConnection implementation is returned which is extended with convenience methods. When the factory is instantiated it itself instantiates a InMemoryDatabase object that needs to be disposed after use. The database is created with the following connection string.
$"Data Source={Guid.NewGuid():N};Mode=Memory;Cache=Shared";
Extension methods for SqliteConnection are provided which facilitates easy creation of very basic test database tables.
void CreateTable<T>(this SqliteConnection connection, string tableName);
Task CreateTableAsync<T>(this SqliteConnection connection, string tableName, CancellationToken cancellationToken = default);
void DropTable(this SqliteConnection connection, string tableName);
Task DropTableAsync(this SqliteConnection connection, string tableName, CancellationToken cancellationToken = default);
Could be extended in the future with attribute support for table keys etc.
Example:
using var factory = new InMemoryConnectionFactory();
var connection = await factory.GetAsync();
await connection.CreateTableAsync<TestModel>("TestTable");
public class TestModel
{
public int Id { get; set; }
public string Title { get; set; }
}
In this example we instantiate an in-memory SQLite database and create a table with the columns defined in the TestModel
class Id
and Title
.
The following is a list of supported .NET types and the SQLite type that they are mapped to when using the CreateTable
methods
.NET | SQLite |
---|---|
bool | INTEGER |
byte | INTEGER |
byte[] | BLOB |
char | TEXT |
DateOnly | TEXT |
DateTime | TEXT |
DateTimeOffset | TEXT |
decimal | TEXT |
double | REAL |
Guid | TEXT |
short | INTEGER |
int | INTEGER |
long | INTEGER |
sbyte | INTEGER |
float | REAL |
string | TEXT |
TimeOnly | TEXT |
TimeSpan | TEXT |
ushort | INTEGER |
uint | INTEGER |
ulong | INTEGER |
I ran into an issue where certain type conversions namely Guid and Date/Time types were not support by default using the Microsoft.Data.Sqlite
provider. The solution was to implement some default type mappers using Dappers SqlMapper
for the problematic types:
SqlMapper.AddTypeHandler(new DateOnlyTypeHandler());
SqlMapper.AddTypeHandler(new GuidTypeHandler());
SqlMapper.AddTypeHandler(new DateTimeOffsetTypeHandler());
SqlMapper.AddTypeHandler(new TimeOnlyTypeHandler());
SqlMapper.AddTypeHandler(new TimeSpanTypeHandler());
These mappers are very basic and you may wish to customize if use for other than testing. A helper method is included that registers all the default implementations:
TypeMapperHelper.RegisterDefaultHandlers();