using System.Collections.Immutable; using HermesSocketLibrary.db; namespace HermesSocketServer.Store.Internal { public abstract class AutoSavedStore : GroupSaveStore where K : class where V : class { private readonly GroupSaveSqlGenerator _generator; private readonly DatabaseTable _table; private readonly Database _database; private readonly Serilog.ILogger _logger; public AutoSavedStore(DatabaseTable table, Database database, Serilog.ILogger logger) : base(logger) { _generator = new GroupSaveSqlGenerator(table.PropertyMapping, logger); _table = table; _database = database; _logger = logger; } public override async Task Save() { var allColumns = _table.KeyColumns.Union(_table.DataColumns).ToArray(); await GenerateQuery(_added, (size) => _generator.GeneratePreparedInsertSql(_table.TableName, size, allColumns), async (query, _, values) => await _generator.DoPreparedStatement(_database, query, values, allColumns)); await GenerateQuery(_modified, (size) => _generator.GeneratePreparedUpdateSql(_table.TableName, size, _table.KeyColumns, _table.DataColumns), async (query, _, values) => await _generator.DoPreparedStatement(_database, query, values, allColumns)); await GenerateQuery(_deleted, (size) => _generator.GeneratePreparedDeleteSql(_table.TableName, size, _table.KeyColumns), async (query, keys, _) => await _generator.DoPreparedStatementRaw(_database, query, keys, _table.KeyColumns)); } private async Task GenerateQuery(IList keys, Func generate, Func, IEnumerable, Task> execute) { ImmutableList? list = null; lock (_lock) { if (!keys.Any()) return; list = keys.ToImmutableList(); keys.Clear(); } var query = generate(list.Count); _logger.Debug($"{_table.TableName} - Adding {list.Count} rows to database: {query}"); var values = list.Select(id => _store[id]).Where(v => v != null); await execute(query, list, values); } } }