DatabaseCfgSource.cs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. using Apq.Cfg.Sources;
  2. using Microsoft.Extensions.Configuration;
  3. using Microsoft.Extensions.Configuration.Memory;
  4. using SqlSugar;
  5. namespace Apq.Cfg.Database;
  6. /// <summary>
  7. /// 数据库配置源
  8. /// </summary>
  9. internal sealed class DatabaseCfgSource : IWritableCfgSource
  10. {
  11. private readonly SqlSugarDatabaseProvider _databaseProvider;
  12. private readonly DatabaseOptions _options;
  13. public DatabaseCfgSource(DatabaseOptions options, int level, bool isPrimaryWriter)
  14. {
  15. _options = options;
  16. Level = level;
  17. IsPrimaryWriter = isPrimaryWriter;
  18. _databaseProvider = CreateProvider(options.Provider!);
  19. }
  20. private static SqlSugarDatabaseProvider CreateProvider(string providerName)
  21. {
  22. var dbType = providerName.ToLowerInvariant() switch
  23. {
  24. "sqlserver" => DbType.SqlServer,
  25. "mysql" => DbType.MySql,
  26. "postgresql" or "postgres" => DbType.PostgreSQL,
  27. "oracle" => DbType.Oracle,
  28. "sqlite" => DbType.Sqlite,
  29. _ => throw new ArgumentException($"不支持的数据库提供程序: '{providerName}'", nameof(providerName))
  30. };
  31. return new SqlSugarDatabaseProvider(dbType);
  32. }
  33. public int Level { get; }
  34. public bool IsWriteable => true;
  35. public bool IsPrimaryWriter { get; }
  36. public IConfigurationSource BuildSource()
  37. {
  38. var data = new List<KeyValuePair<string, string?>>();
  39. try
  40. {
  41. using var cts = new CancellationTokenSource(_options.CommandTimeoutMs);
  42. var configData = _databaseProvider.LoadConfigurationAsync(
  43. _options.ConnectionString!, _options.Table!, _options.KeyColumn!, _options.ValueColumn!,
  44. cts.Token).GetAwaiter().GetResult();
  45. foreach (var (key, value) in configData)
  46. data.Add(new KeyValuePair<string, string?>(key, value));
  47. }
  48. catch { }
  49. return new MemoryConfigurationSource { InitialData = data };
  50. }
  51. public async Task ApplyChangesAsync(IReadOnlyDictionary<string, string?> changes, CancellationToken cancellationToken)
  52. {
  53. using var timeoutCts = new CancellationTokenSource(_options.CommandTimeoutMs);
  54. using var linked = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutCts.Token);
  55. await _databaseProvider.ApplyChangesAsync(
  56. _options.ConnectionString!, _options.Table!, _options.KeyColumn!, _options.ValueColumn!,
  57. changes, linked.Token).ConfigureAwait(false);
  58. }
  59. }