Fix: Migrating from SQLite was crashing in some conditions (Close #4623)

This commit is contained in:
nicolas.dorier
2023-02-15 15:59:45 +09:00
parent 8b80910d70
commit 5121d64022
2 changed files with 19 additions and 2 deletions

View File

@@ -31,12 +31,12 @@ namespace BTCPayServer.Data
{ {
_designTime = designTime; _designTime = designTime;
} }
#nullable enable
public async Task<string?> GetMigrationState() public async Task<string?> GetMigrationState()
{ {
return (await Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value; return (await Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value;
} }
#nullable restore
public DbSet<AddressInvoiceData> AddressInvoices { get; set; } public DbSet<AddressInvoiceData> AddressInvoices { get; set; }
public DbSet<APIKeyData> ApiKeys { get; set; } public DbSet<APIKeyData> ApiKeys { get; set; }
public DbSet<AppData> Apps { get; set; } public DbSet<AppData> Apps { get; set; }

View File

@@ -4,6 +4,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -213,12 +214,28 @@ namespace BTCPayServer.Hosting
var typeMapping = t.EntityTypeMappings.Single(); var typeMapping = t.EntityTypeMappings.Single();
var query = (IQueryable<object>)otherContext.GetType().GetMethod("Set", new Type[0])!.MakeGenericMethod(typeMapping.EntityType.ClrType).Invoke(otherContext, null)!; var query = (IQueryable<object>)otherContext.GetType().GetMethod("Set", new Type[0])!.MakeGenericMethod(typeMapping.EntityType.ClrType).Invoke(otherContext, null)!;
Logger.LogInformation($"Migrating table: " + t.Name); Logger.LogInformation($"Migrating table: " + t.Name);
List<PropertyInfo> datetimeProperties = new List<PropertyInfo>();
foreach (var col in t.Columns)
if (col.PropertyMappings.Single().Property.ClrType == typeof(DateTime))
{
datetimeProperties.Add(col.PropertyMappings.Single().Property.PropertyInfo!);
}
var rows = await query.ToListAsync(); var rows = await query.ToListAsync();
foreach (var row in rows) foreach (var row in rows)
{ {
// There is as circular deps between invoice and refund. // There is as circular deps between invoice and refund.
if (row is InvoiceData id) if (row is InvoiceData id)
id.CurrentRefundId = null; id.CurrentRefundId = null;
foreach (var prop in datetimeProperties)
{
var v = (DateTime)prop.GetValue(row)!;
if (v.Kind == DateTimeKind.Unspecified)
{
v = new DateTime(v.Ticks, DateTimeKind.Utc);
prop.SetValue(row, v);
}
}
postgresContext.Entry(row).State = EntityState.Added; postgresContext.Entry(row).State = EntityState.Added;
} }
await postgresContext.SaveChangesAsync(); await postgresContext.SaveChangesAsync();