-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDatabaseService.cs
More file actions
99 lines (80 loc) · 3.38 KB
/
Copy pathDatabaseService.cs
File metadata and controls
99 lines (80 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using FreeSql;
using Serilog;
using SquidStd.Database.Abstractions.Data.Database;
using SquidStd.Database.Abstractions.Types.Data;
using SquidStd.Core.Directories;
using SquidStd.Database.Connection;
using SquidStd.Database.Interfaces.Services;
namespace SquidStd.Database.Services;
/// <summary>
/// Builds and owns the singleton FreeSql instance, logging SQL and migrations verbosely.
/// </summary>
public sealed class DatabaseService : IDatabaseService
{
private static readonly ILogger Logger = Log.ForContext<DatabaseService>();
private readonly DatabaseConfig _config;
private readonly DirectoriesConfig _directories;
private IFreeSql? _orm;
private int _started;
/// <inheritdoc />
public IFreeSql Orm => _orm ?? throw new InvalidOperationException("Database service is not started.");
/// <summary>
/// Initializes the database service.
/// </summary>
/// <param name="config">The database configuration section.</param>
/// <param name="directories">The directories configuration, providing the root directory.</param>
public DatabaseService(DatabaseConfig config, DirectoriesConfig directories)
{
_config = config;
_directories = directories;
}
/// <inheritdoc />
public ValueTask StartAsync(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
if (Interlocked.Exchange(ref _started, 1) != 0)
{
return ValueTask.CompletedTask;
}
var parsed = ConnectionStringParser.Parse(_config.ConnectionString, _directories.Root);
if (parsed.SqliteFilePath is { } sqliteFile)
{
var directory = Path.GetDirectoryName(sqliteFile);
if (!string.IsNullOrEmpty(directory))
{
Directory.CreateDirectory(directory);
}
}
Logger.Verbose("Building FreeSql for provider {Provider}", parsed.Provider);
var builder = new FreeSqlBuilder()
.UseConnectionString(MapDataType(parsed.Provider), parsed.NativeConnectionString)
.UseAutoSyncStructure(_config.AutoMigrate)
.UseMonitorCommand(cmd => Logger.Verbose("SQL {Sql}", cmd.CommandText));
_orm = builder.Build();
_orm.Aop.SyncStructureAfter += (_, e) =>
Logger.Verbose("Migrated {Entities} -> {Sql}", e.EntityTypes, e.Sql);
Logger.Information(
"Database service started ({Provider}, autoMigrate={AutoMigrate})",
parsed.Provider,
_config.AutoMigrate
);
return ValueTask.CompletedTask;
}
/// <inheritdoc />
public ValueTask StopAsync(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
_orm?.Dispose();
_orm = null;
return ValueTask.CompletedTask;
}
private static DataType MapDataType(DatabaseProviderType provider)
=> provider switch
{
DatabaseProviderType.Sqlite => DataType.Sqlite,
DatabaseProviderType.Postgres => DataType.PostgreSQL,
DatabaseProviderType.SqlServer => DataType.SqlServer,
DatabaseProviderType.MySql => DataType.MySql,
_ => throw new NotSupportedException($"Unsupported provider {provider}.")
};
}