1+ using System . Diagnostics ;
2+ using System . Linq . Expressions ;
3+ using System . Reflection ;
4+ using Microsoft . EntityFrameworkCore ;
5+ using Microsoft . EntityFrameworkCore . Metadata . Builders ;
6+ using Microsoft . Extensions . DependencyInjection ;
7+ using MyJetTools . Telemetry ;
8+
9+ // ReSharper disable UnusedMember.Global
10+
11+ namespace MyJetTools . Sdk . EfPostgres
12+ {
13+ public static class DataBaseHelper
14+ {
15+ public static void AddDatabase < T > ( this IServiceCollection services , string schema , string connectionString ,
16+ Func < DbContextOptions , T > contextFactory ,
17+ bool replaceSllInstruction = true )
18+ where T : DbContext
19+ {
20+ AppContext . SetSwitch ( "Npgsql.DisableDateTimeInfinityConversions" , true ) ;
21+
22+ connectionString = PrepareConnectionString ( connectionString , replaceSllInstruction ) ;
23+
24+ services . AddSingleton ( _ =>
25+ {
26+ var optionsBuilder = new DbContextOptionsBuilder < T > ( ) ;
27+ optionsBuilder . UseNpgsql ( connectionString ,
28+ builder =>
29+ builder . MigrationsHistoryTable (
30+ $ "__EFMigrationsHistory_{ schema } ",
31+ schema ) ) ;
32+
33+ return optionsBuilder ;
34+ } ) ;
35+
36+ var contextOptions = services . BuildServiceProvider ( ) . GetRequiredService < DbContextOptionsBuilder < T > > ( ) ;
37+
38+ using var activity = TelemetrySource . StartActivity ( "database migration" ) ;
39+ {
40+ Console . WriteLine ( "======= begin database migration =======" ) ;
41+ var sw = new Stopwatch ( ) ;
42+ sw . Start ( ) ;
43+
44+ using var context = contextFactory ( contextOptions . Options ) ;
45+
46+ context . Database . Migrate ( ) ;
47+
48+ sw . Stop ( ) ;
49+ Console . WriteLine ( $ "======= end database migration ({ sw . Elapsed . ToString ( ) } ) =======") ;
50+ }
51+ }
52+
53+ private static string PrepareConnectionString ( string connectionString , bool replaceSllInstruction )
54+ {
55+ if ( ! connectionString . Contains ( "ApplicationName" ) )
56+ {
57+ var appName = Environment . GetEnvironmentVariable ( "ENV_INFO" ) ??
58+ Assembly . GetEntryAssembly ( ) ? . GetName ( ) . Name ;
59+
60+ connectionString = connectionString . Last ( ) != ';'
61+ ? $ "{ connectionString } ;ApplicationName={ appName } "
62+ : $ "{ connectionString } ApplicationName={ appName } ";
63+ }
64+
65+ if ( replaceSllInstruction )
66+ connectionString = connectionString . Replace ( "Ssl Mode=Require" , "Ssl Mode=VerifyFull" ) ;
67+
68+ return connectionString ;
69+ }
70+
71+ public static void AddDatabaseWithoutMigrations < T > ( this IServiceCollection services , string schema ,
72+ string connectionString ,
73+ bool replaceSllInstruction = true )
74+ where T : DbContext
75+ {
76+ AppContext . SetSwitch ( "Npgsql.DisableDateTimeInfinityConversions" , true ) ;
77+
78+ connectionString = PrepareConnectionString ( connectionString , replaceSllInstruction ) ;
79+
80+ services . AddSingleton ( x =>
81+ {
82+ var optionsBuilder = new DbContextOptionsBuilder < T > ( ) ;
83+ optionsBuilder . UseNpgsql ( connectionString ,
84+ builder =>
85+ builder . MigrationsHistoryTable (
86+ $ "__EFMigrationsHistory_{ schema } ",
87+ schema ) ) ;
88+
89+ return optionsBuilder ;
90+ } ) ;
91+ }
92+
93+ public static PropertyBuilder < DateTime > SpecifyKindUtc < TEntity > (
94+ this EntityTypeBuilder < TEntity > builder ,
95+ Expression < Func < TEntity , DateTime > > propertyExpression )
96+ where TEntity : class
97+ {
98+ var res = builder
99+ . Property ( propertyExpression )
100+ . HasConversion (
101+ v => DateTime . SpecifyKind ( v , DateTimeKind . Utc ) ,
102+ v => DateTime . SpecifyKind ( v , DateTimeKind . Utc ) ) ;
103+
104+ return res ;
105+ }
106+ }
107+ }
0 commit comments