Move database/mapper setup code to Core

This commit is contained in:
Ske 2019-05-19 22:03:28 +02:00
parent 08afa2543b
commit 8b8ec80944
4 changed files with 62 additions and 45 deletions

View File

@ -27,21 +27,8 @@ namespace PluralKit.Bot
private async Task MainAsync()
{
Console.WriteLine("Starting PluralKit...");
// Dapper by default tries to pass ulongs to Npgsql, which rejects them since PostgreSQL technically
// doesn't support unsigned types on its own.
// Instead we add a custom mapper to encode them as signed integers instead, converting them back and forth.
SqlMapper.RemoveTypeMap(typeof(ulong));
SqlMapper.AddTypeHandler<ulong>(new UlongEncodeAsLongHandler());
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
// Also, use NodaTime. it's good.
NpgsqlConnection.GlobalTypeMapper.UseNodaTime();
// With the thing we add above, Npgsql already handles NodaTime integration
// This makes Dapper confused since it thinks it has to convert it anyway and doesn't understand the types
// So we add a custom type handler that literally just passes the type through to Npgsql
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>());
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<LocalDate>());
DatabaseUtils.Init();
using (var services = BuildServiceProvider())
{

View File

@ -61,33 +61,6 @@ namespace PluralKit.Bot
}
}
class UlongEncodeAsLongHandler : SqlMapper.TypeHandler<ulong>
{
public override ulong Parse(object value)
{
// Cast to long to unbox, then to ulong (???)
return (ulong)(long)value;
}
public override void SetValue(IDbDataParameter parameter, ulong value)
{
parameter.Value = (long)value;
}
}
class PassthroughTypeHandler<T> : SqlMapper.TypeHandler<T>
{
public override void SetValue(IDbDataParameter parameter, T value)
{
parameter.Value = value;
}
public override T Parse(object value)
{
return (T) value;
}
}
class PKSystemTypeReader : TypeReader
{
public override async Task<TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services)

View File

@ -0,0 +1,55 @@
using System.Data;
using Dapper;
using NodaTime;
using Npgsql;
namespace PluralKit
{
public static class DatabaseUtils
{
public static void Init()
{
// Dapper by default tries to pass ulongs to Npgsql, which rejects them since PostgreSQL technically
// doesn't support unsigned types on its own.
// Instead we add a custom mapper to encode them as signed integers instead, converting them back and forth.
SqlMapper.RemoveTypeMap(typeof(ulong));
SqlMapper.AddTypeHandler<ulong>(new UlongEncodeAsLongHandler());
Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;
// Also, use NodaTime. it's good.
NpgsqlConnection.GlobalTypeMapper.UseNodaTime();
// With the thing we add above, Npgsql already handles NodaTime integration
// This makes Dapper confused since it thinks it has to convert it anyway and doesn't understand the types
// So we add a custom type handler that literally just passes the type through to Npgsql
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<Instant>());
SqlMapper.AddTypeHandler(new PassthroughTypeHandler<LocalDate>());
}
class UlongEncodeAsLongHandler : SqlMapper.TypeHandler<ulong>
{
public override ulong Parse(object value)
{
// Cast to long to unbox, then to ulong (???)
return (ulong)(long)value;
}
public override void SetValue(IDbDataParameter parameter, ulong value)
{
parameter.Value = (long)value;
}
}
class PassthroughTypeHandler<T> : SqlMapper.TypeHandler<T>
{
public override void SetValue(IDbDataParameter parameter, T value)
{
parameter.Value = value;
}
public override T Parse(object value)
{
return (T) value;
}
}
}
}

View File

@ -20,14 +20,16 @@ namespace PluralKit.Web
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
DatabaseUtils.Init();
var config = Configuration.GetSection("PluralKit").Get<CoreConfig>();
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services
.AddSingleton<IDbConnection, NpgsqlConnection>(_ => new NpgsqlConnection(config.Database))
.AddSingleton<SystemStore>()
.AddSingleton<MemberStore>()
.AddScoped<IDbConnection, NpgsqlConnection>(_ => new NpgsqlConnection(config.Database))
.AddTransient<SystemStore>()
.AddTransient<MemberStore>()
.AddSingleton(config);
}