Move database/mapper setup code to Core
This commit is contained in:
parent
08afa2543b
commit
8b8ec80944
@ -28,20 +28,7 @@ namespace PluralKit.Bot
|
||||
{
|
||||
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())
|
||||
{
|
||||
|
@ -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)
|
||||
|
55
PluralKit.Core/DatabaseUtils.cs
Normal file
55
PluralKit.Core/DatabaseUtils.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user