Dapper.DDD.Repository.PostGreSql 1.8.0

dotnet add package Dapper.DDD.Repository.PostGreSql --version 1.8.0
NuGet\Install-Package Dapper.DDD.Repository.PostGreSql -Version 1.8.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Dapper.DDD.Repository.PostGreSql" Version="1.8.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Dapper.DDD.Repository.PostGreSql --version 1.8.0
#r "nuget: Dapper.DDD.Repository.PostGreSql, 1.8.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Dapper.DDD.Repository.PostGreSql as a Cake Addin
#addin nuget:?package=Dapper.DDD.Repository.PostGreSql&version=1.8.0

// Install Dapper.DDD.Repository.PostGreSql as a Cake Tool
#tool nuget:?package=Dapper.DDD.Repository.PostGreSql&version=1.8.0

Dapper.DDD.Repository.PostGreSql

This package provides support for using Dapper.DDD.Repository with PostGreSql.

Usage

Install the package Npgsql in your project. Then simply provide an instance of PostGreSqlQueryGenerator as your QueryGenerator, and create a PostGreSqlConnectionFactory in your project, and you're done:

	...
	options.ConnectionFactory = new PostGreSqlConnectionFactory("CONNECTIONSTRING");
	options.QueryGeneratorFactory = new PostGreSqlQueryGeneratorFactory();
	...

Also here's a simple PostGreSqlConnectionFactory you can use:

using System.Data;
using Dapper.DDD.Repository.Interfaces;
using Npgsql;

namespace YOUR_NAMESPACE_HERE;

public class PostGreSqlConnectionFactory : IConnectionFactory
{
	private readonly string _connectionString;

	public PostGreSqlConnectionFactory(string connectionString)
	{
		if (string.IsNullOrWhiteSpace(connectionString))
		{
			throw new ArgumentException("connectionString cannot be null or whitespace.", nameof(connectionString));
		}

		_connectionString = connectionString;
	}

	public IDbConnection CreateConnection()
	{
		return new NpgsqlConnection(_connectionString);
	}
}

Using Geometry and Geography

Dapper doesn't inherently play that well with these column types, however this package has a solution for it. In this example I'll use NetTopologySuite for my C# Geometry classes, but the principle is the same if you're using Microsoft's classes (or even some other third party).

Apart from NetTopologySuite you'll want to install the Npgsql.NetTopologySuite package as well.

This solution uses the PostGIS extension in your PostGreSql database and contains a few steps.

Assume a table looking like this:

CREATE TABLE cities
(
	Id UUID NOT NULL PRIMARY KEY,
	Name char varying(200) NOT NULL,
	GeoLocation GEOMETRY(POINT, 25832) NOT NULL
);

And it's equivalent C# class looking like this:

public record City
{
	public Guid Id { get; set; }
	public string Name { get; set; }
	public Point GeoLocation { get; set; }
}

We'll need to do the following to enable this:

Connection Factory

public class PostGreSqlConnectionFactory : IConnectionFactory
{
	private readonly NpgsqlDataSource _dataSource;

	public PostGreSqlConnectionFactory(string connectionString)
	{
		if (string.IsNullOrWhiteSpace(connectionString))
		{
			throw new ArgumentException("connectionString cannot be null or whitespace.", nameof(connectionString));
		}

		var dataSourceBuilder = new NpgsqlDataSourceBuilder(connectionString);
		dataSourceBuilder.UseNetTopologySuite();
		_dataSource = dataSourceBuilder.Build();
	}

	~PostGreSqlConnectionFactory()
	{
		_dataSource.Dispose();
	}

	public IDbConnection CreateConnection()
	{
		return _dataSource.CreateConnection();
	}
}

This allows us to call UseNetTopologySuite which is crucial. It also introduces a finalizer for cleaning up the datasource, as IDisposable isn't really feasible with the Factory classes at the moment.

Dapper Type Mappers

In this example I'll use a mapper for Point, but feel free to add more as you introduce more types:

public class PointTypeMapper : SqlMapper.TypeHandler<Point>
{
	public override void SetValue(IDbDataParameter parameter, Point value)
	{
		parameter.Value = (object?)value?.AsBinary() ?? DBNull.Value;
		parameter.DbType = DbType.Binary;
	}

	public override Point Parse(object? value)
	{
		if (value is null or DBNull)
			return null!;

		return (Point)value;
	}
}

Configuration

The final step is to configure Dapper and the repository extension:

SqlMapper.AddTypeHandler(new PointTypeMapper());
...

services.ConfigureDapperRepositoryDefaults(options =>
{
	options.ConnectionFactory = new PostGreSqlConnectionFactory(connectionString);
	options.DapperInjectionFactory = new DapperInjectionFactory();
	options.QueryGeneratorFactory = new PostGreSqlQueryGeneratorFactory();
	options.TreatAsBuiltInType<Point>(); // Necessary to allow the SqlMapper to work its magic
	...
});

This does two things:

  • Configures Dapper to use the PointTypeMapper we've defined
  • Configures the Repository extension to treat the Pont type as a built-in type, which means all the "automagic" functionality of the Repository extension is disabled and Dapper gets to do its thing alone (which is to use the PointTypeMapper)

And that's basically it, now you can define properties of the type Point in any of your aggregates and the built-in ITableRepository will work correctly.

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.8.0 126 1/16/2024
1.7.0 187 3/10/2023