diff --git a/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs b/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs index c918fea1ed..8be3c8eea8 100644 --- a/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs +++ b/src/Tgstation.Server.Host/Database/SqliteDatabaseContext.cs @@ -1,7 +1,9 @@ using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using System; +using System.Linq; using Tgstation.Server.Host.Configuration; namespace Tgstation.Server.Host.Database @@ -28,6 +30,33 @@ namespace Tgstation.Server.Host.Database options.UseSqlite(DatabaseConfiguration.ConnectionString); } + /// + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + // Shamelessly stolen from https://blog.dangl.me/archive/handling-datetimeoffset-in-sqlite-with-entity-framework-core/ + + // SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations + // here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations + // To work around this, when the Sqlite database provider is used, all model properties of type DateTimeOffset + // use the DateTimeOffsetToBinaryConverter + // Based on: https://github.com/aspnet/EntityFrameworkCore/issues/10784#issuecomment-415769754 + // This only supports millisecond precision, but should be sufficient for most use cases. + foreach (var entityType in modelBuilder.Model.GetEntityTypes()) + { + var properties = entityType + .ClrType + .GetProperties() + .Where(p => p.PropertyType == typeof(DateTimeOffset) || p.PropertyType == typeof(DateTimeOffset?)); + foreach (var property in properties) + modelBuilder + .Entity(entityType.Name) + .Property(property.Name) + .HasConversion(new DateTimeOffsetToBinaryConverter()); + } + } + /// protected override void ValidateDatabaseType() {