| | | 1 | | namespace ZhEaIsNsAaBn.DbSeeder.Design; |
| | | 2 | | |
| | | 3 | | /// <summary> |
| | | 4 | | /// <c>{output}/.snapshot/{Entity}.json</c>: the seed rows as of the last <c>add</c> / <c>baseline</c> / <c>snapshot reb |
| | | 5 | | /// form (<c>Upsert</c> = every row, <c>SoftDelete</c> = keys of rows soft-deleted then). Design-time only, never embedd |
| | | 6 | | /// </summary> |
| | | 7 | | internal static class SeedSnapshot |
| | | 8 | | { |
| | | 9 | | public const string Folder = ".snapshot"; |
| | | 10 | | |
| | | 11 | | |
| | 693 | 12 | | public static string PathOf( string outputFolder, ExportedTable table ) => Path.Combine( outputFolder, Folder, table |
| | | 13 | | |
| | | 14 | | public static DesignTable ToFile( ExportedTable table ) |
| | | 15 | | { |
| | 876 | 16 | | var file = new DesignTable { Entity = table.Shape.EntityType.Name, MatchBy = table.Shape.IsBusinessKey ? table.M |
| | | 17 | | |
| | 876 | 18 | | file.Upsert.AddRange( table.Rows ); |
| | 876 | 19 | | file.SoftDelete.AddRange( table.Rows.Where( r => table.SoftDeleted.Contains( r.Key ) ).Select( r => r.Only( tabl |
| | | 20 | | |
| | 876 | 21 | | return file; |
| | | 22 | | } |
| | | 23 | | |
| | | 24 | | public static void Write( string outputFolder, ExportedTable table ) |
| | | 25 | | { |
| | 480 | 26 | | var path = PathOf( outputFolder, table ); |
| | | 27 | | |
| | 480 | 28 | | Directory.CreateDirectory( Path.GetDirectoryName( path )! ); |
| | 480 | 29 | | File.WriteAllText( path, SeedFileWriter.Table( ToFile( table ) ), new UTF8Encoding( false ) ); |
| | 480 | 30 | | } |
| | | 31 | | |
| | | 32 | | /// The snapshot of <paramref name="current"/>'s table, read back into the same row form; <see langword="null"/> whe |
| | | 33 | | /// <exception cref="InvalidOperationException">The file can't be parsed.</exception> |
| | | 34 | | public static ExportedTable? Read( string outputFolder, ExportedTable current ) |
| | | 35 | | { |
| | 213 | 36 | | var path = PathOf( outputFolder, current ); |
| | | 37 | | |
| | 216 | 38 | | if ( !File.Exists( path ) ) { return null; } |
| | | 39 | | |
| | | 40 | | |
| | | 41 | | SeedTableFile file; |
| | | 42 | | |
| | 420 | 43 | | try { file = JsonSerializer.Deserialize<SeedTableFile>( File.ReadAllText( path ), SeedMigrationSource.JsonOption |
| | 0 | 44 | | catch ( JsonException ex ) { throw new InvalidOperationException( $"{path} can't be read: {ex.Message}", ex ); } |
| | | 45 | | |
| | | 46 | | |
| | 210 | 47 | | var match = current.MatchNames; |
| | | 48 | | |
| | | 49 | | string KeyOf( IReadOnlyDictionary<string, JsonElement> row ) => SeedKeyComparer.Key( match.Select( m => row.TryG |
| | | 50 | | |
| | 210 | 51 | | return new ExportedTable |
| | 210 | 52 | | { |
| | 210 | 53 | | Shape = current.Shape, |
| | 210 | 54 | | Rows = file.Upsert.Select( r => new DesignRow( KeyOf( r ), r.Select( p => (p.Key, p.Value. |
| | 210 | 55 | | SoftDeleted = file.SoftDelete.Select( KeyOf ).ToHashSet( StringComparer.Ordinal ) |
| | 210 | 56 | | }; |
| | | 57 | | } |
| | | 58 | | } |