Added & using prepared statements for stores
This commit is contained in:
		| @@ -1,3 +1,4 @@ | ||||
| using System.Collections.Immutable; | ||||
| using HermesSocketLibrary.db; | ||||
| using HermesSocketServer.Models; | ||||
|  | ||||
| @@ -23,7 +24,7 @@ namespace HermesSocketServer.Store | ||||
|                 { "ttsVoiceId", "VoiceId" }, | ||||
|                 { "userId", "UserId" }, | ||||
|             }; | ||||
|             _generator = new GroupSaveSqlGenerator<ChatterVoice>(ctp); | ||||
|             _generator = new GroupSaveSqlGenerator<ChatterVoice>(ctp, _logger); | ||||
|         } | ||||
|  | ||||
|         public override async Task Load() | ||||
| @@ -55,46 +56,53 @@ namespace HermesSocketServer.Store | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public override async Task<bool> Save() | ||||
|         public override async Task Save() | ||||
|         { | ||||
|             int count = 0; | ||||
|             string sql = string.Empty; | ||||
|             ImmutableList<string>? list = null; | ||||
|  | ||||
|             if (_added.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _added.Count; | ||||
|                     sql = _generator.GenerateInsertSql("TtsChatVoice", _added.Select(a => _store[a]), ["userId", "chatterId", "ttsVoiceId"]); | ||||
|                     list = _added.ToImmutableList(); | ||||
|                     _added.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedInsertSql("TtsChatVoice", count, ["userId", "chatterId", "ttsVoiceId"]); | ||||
|  | ||||
|                 _logger.Debug($"TtsChatVoice - Adding {count} rows to database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 _logger.Debug($"User - Adding {count} rows to database: {sql}"); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|             } | ||||
|             if (_modified.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _modified.Count; | ||||
|                     sql = _generator.GenerateUpdateSql("TtsChatVoice", _modified.Select(m => _store[m]), ["userId", "chatterId"], ["ttsVoiceId"]); | ||||
|                     list = _modified.ToImmutableList(); | ||||
|                     _modified.Clear(); | ||||
|                 } | ||||
|                 _logger.Debug($"TtsChatVoice - Modifying {count} rows in database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedUpdateSql("TtsChatVoice", count, ["userId", "chatterId"], ["ttsVoiceId"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Modifying {count} rows in database: {sql}"); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|             } | ||||
|             if (_deleted.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _deleted.Count; | ||||
|                     sql = _generator.GenerateDeleteSql("TtsChatVoice", _deleted, ["userId", "chatterId"]); | ||||
|                     list = _deleted.ToImmutableList(); | ||||
|                     _deleted.Clear(); | ||||
|                 } | ||||
|                 _logger.Debug($"TtsChatVoice - Deleting {count} rows from database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedDeleteSql("TtsChatVoice", count, ["userId", "chatterId"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Deleting {count} rows from database: {sql}"); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, list, ["id"]); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,15 +1,18 @@ | ||||
| using System.Reflection; | ||||
| using System.Text; | ||||
| using HermesSocketLibrary.db; | ||||
|  | ||||
| namespace HermesSocketServer.Store | ||||
| { | ||||
|     public class GroupSaveSqlGenerator<T> | ||||
|     { | ||||
|         private readonly IDictionary<string, PropertyInfo?> columnPropertyRelations; | ||||
|         private readonly Serilog.ILogger _logger; | ||||
|  | ||||
|         public GroupSaveSqlGenerator(IDictionary<string, string> columnsToProperties) | ||||
|         public GroupSaveSqlGenerator(IDictionary<string, string> columnsToProperties, Serilog.ILogger logger) | ||||
|         { | ||||
|             columnPropertyRelations = columnsToProperties.ToDictionary(p => p.Key, p => typeof(T).GetProperty(p.Value)); | ||||
|             _logger = logger; | ||||
|  | ||||
|             var nullProperties = columnPropertyRelations.Where(p => p.Value == null) | ||||
|                 .Select(p => columnsToProperties[p.Key]); | ||||
| @@ -17,6 +20,24 @@ namespace HermesSocketServer.Store | ||||
|                 throw new ArgumentException("Some properties do not exist on the values given: " + string.Join(", ", nullProperties)); | ||||
|         } | ||||
|  | ||||
|         public async Task DoPreparedStatement<V>(Database database, string sql, IEnumerable<V> values, string[] columns) | ||||
|         { | ||||
|             await database.Execute(sql, (c) => | ||||
|             { | ||||
|                 var valueCounter = 0; | ||||
|                 foreach (var value in values) | ||||
|                 { | ||||
|                     foreach (var column in columns) | ||||
|                     { | ||||
|                         var propValue = columnPropertyRelations[column]!.GetValue(value); | ||||
|                         var propType = columnPropertyRelations[column]!.PropertyType; | ||||
|                         c.Parameters.AddWithValue(column.ToLower() + valueCounter, propValue ?? DBNull.Value); | ||||
|                     } | ||||
|                     valueCounter++; | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         public string GenerateInsertSql(string table, IEnumerable<T> values, IEnumerable<string> columns) | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(table)) | ||||
| @@ -40,11 +61,42 @@ namespace HermesSocketServer.Store | ||||
|                 { | ||||
|                     var propValue = columnPropertyRelations[column]!.GetValue(value); | ||||
|                     var propType = columnPropertyRelations[column]!.PropertyType; | ||||
|                     WriteValue(sb, propValue, propType); | ||||
|                     WriteValue(sb, propValue ?? DBNull.Value, propType); | ||||
|                     sb.Append(","); | ||||
|                 } | ||||
|                 sb.Remove(sb.Length - 1, 1) | ||||
|                 .Append("),"); | ||||
|                     .Append("),"); | ||||
|             } | ||||
|             sb.Remove(sb.Length - 1, 1) | ||||
|                 .Append(';'); | ||||
|             return sb.ToString(); | ||||
|         } | ||||
|  | ||||
|         public string GeneratePreparedInsertSql(string table, int rows, IEnumerable<string> columns) | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(table)) | ||||
|                 throw new ArgumentException("Value is either null or whitespace-filled.", nameof(table)); | ||||
|             if (columns == null) | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             if (!columns.Any()) | ||||
|                 throw new ArgumentException("Empty list given.", nameof(columns)); | ||||
|  | ||||
|             var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]); | ||||
|             var sb = new StringBuilder(); | ||||
|             var columnsLower = columns.Select(c => c.ToLower()); | ||||
|             sb.Append($"INSERT INTO \"{table}\" (\"{string.Join("\", \"", columns)}\") VALUES "); | ||||
|             for (var row = 0; row < rows; row++) | ||||
|             { | ||||
|                 sb.Append("("); | ||||
|                 foreach (var column in columnsLower) | ||||
|                 { | ||||
|                     sb.Append('@') | ||||
|                         .Append(column) | ||||
|                         .Append(row) | ||||
|                         .Append(", "); | ||||
|                 } | ||||
|                 sb.Remove(sb.Length - 2, 2) | ||||
|                     .Append("),"); | ||||
|             } | ||||
|             sb.Remove(sb.Length - 1, 1) | ||||
|                 .Append(';'); | ||||
| @@ -93,6 +145,44 @@ namespace HermesSocketServer.Store | ||||
|             return sb.ToString(); | ||||
|         } | ||||
|  | ||||
|         public string GeneratePreparedUpdateSql(string table, int rows, IEnumerable<string> keyColumns, IEnumerable<string> updateColumns) | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(table)) | ||||
|                 throw new ArgumentException("Value is either null or whitespace-filled.", nameof(table)); | ||||
|             if (keyColumns == null) | ||||
|                 throw new ArgumentNullException(nameof(keyColumns)); | ||||
|             if (!keyColumns.Any()) | ||||
|                 throw new ArgumentException("Empty list given.", nameof(keyColumns)); | ||||
|             if (updateColumns == null) | ||||
|                 throw new ArgumentNullException(nameof(updateColumns)); | ||||
|             if (!updateColumns.Any()) | ||||
|                 throw new ArgumentException("Empty list given.", nameof(updateColumns)); | ||||
|  | ||||
|             var columns = keyColumns.Union(updateColumns); | ||||
|             var ctp = columns.ToDictionary(c => c, c => columnPropertyRelations[c]); | ||||
|             var sb = new StringBuilder(); | ||||
|             sb.Append($"UPDATE \"{table}\" as t SET {string.Join(", ", updateColumns.Select(c => "\"" + c + "\" = c.\"" + c + "\""))} FROM (VALUES "); | ||||
|             for (var row = 0; row < rows; row++) | ||||
|             { | ||||
|                 sb.Append("("); | ||||
|                 foreach (var column in columns) | ||||
|                 { | ||||
|                     sb.Append('@') | ||||
|                         .Append(column) | ||||
|                         .Append(row) | ||||
|                         .Append(", "); | ||||
|                 } | ||||
|                 sb.Remove(sb.Length - 2, 2) | ||||
|                     .Append("),"); | ||||
|             } | ||||
|             sb.Remove(sb.Length - 1, 1) | ||||
|                 .Append($") AS c(\"{string.Join("\", \"", columns)}\") WHERE ") | ||||
|                 .Append(string.Join(" AND ", keyColumns.Select(c => "t.\"" + c + "\" = c.\"" + c + "\""))) | ||||
|                 .Append(";"); | ||||
|  | ||||
|             return sb.ToString(); | ||||
|         } | ||||
|  | ||||
|         public string GenerateDeleteSql(string table, IEnumerable<string> keys, IEnumerable<string> keyColumns) | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(table)) | ||||
| @@ -127,6 +217,37 @@ namespace HermesSocketServer.Store | ||||
|             return sb.ToString(); | ||||
|         } | ||||
|  | ||||
|         public string GeneratePreparedDeleteSql(string table, int rows, IEnumerable<string> keyColumns) | ||||
|         { | ||||
|             if (string.IsNullOrWhiteSpace(table)) | ||||
|                 throw new ArgumentException("Value is either null or whitespace-filled.", nameof(table)); | ||||
|             if (keyColumns == null) | ||||
|                 throw new ArgumentNullException(nameof(keyColumns)); | ||||
|             if (!keyColumns.Any()) | ||||
|                 throw new ArgumentException("Empty list given.", nameof(keyColumns)); | ||||
|  | ||||
|             var ctp = keyColumns.ToDictionary(c => c, c => columnPropertyRelations[c]); | ||||
|             var sb = new StringBuilder(); | ||||
|             sb.Append($"DELETE FROM \"{table}\" WHERE (\"{string.Join("\", \"", keyColumns)}\") IN ("); | ||||
|             for (var row = 0; row < rows; row++) | ||||
|             { | ||||
|                 sb.Append("("); | ||||
|                 foreach (var column in keyColumns) | ||||
|                 { | ||||
|                     sb.Append('@') | ||||
|                         .Append(column) | ||||
|                         .Append(row) | ||||
|                         .Append(", "); | ||||
|                 } | ||||
|                 sb.Remove(sb.Length - 2, 2) | ||||
|                     .Append("),"); | ||||
|             } | ||||
|             sb.Remove(sb.Length - 1, 1) | ||||
|                 .Append(");"); | ||||
|  | ||||
|             return sb.ToString(); | ||||
|         } | ||||
|  | ||||
|         private void WriteValue(StringBuilder sb, object? value, Type type) | ||||
|         { | ||||
|             if (type == typeof(string)) | ||||
| @@ -134,9 +255,9 @@ namespace HermesSocketServer.Store | ||||
|                     .Append(value) | ||||
|                     .Append("'"); | ||||
|             else if (type == typeof(Guid)) | ||||
|                 sb.Append("'") | ||||
|                 sb.Append("uuid('") | ||||
|                     .Append(value?.ToString()) | ||||
|                     .Append("'"); | ||||
|                     .Append("')"); | ||||
|             else if (type == typeof(TimeSpan)) | ||||
|                 sb.Append(((TimeSpan)value).TotalMilliseconds); | ||||
|             else | ||||
|   | ||||
| @@ -28,7 +28,7 @@ namespace HermesSocketServer.Store | ||||
|         protected abstract void OnInitialAdd(K key, V value); | ||||
|         protected abstract void OnInitialModify(K key, V value); | ||||
|         protected abstract void OnInitialRemove(K key); | ||||
|         public abstract Task<bool> Save(); | ||||
|         public abstract Task Save(); | ||||
|  | ||||
|         public V? Get(K key) | ||||
|         { | ||||
|   | ||||
| @@ -7,7 +7,7 @@ namespace HermesSocketServer.Store | ||||
|         Task Load(); | ||||
|         bool Modify(K? key, Action<V> action); | ||||
|         void Remove(K? key); | ||||
|         Task<bool> Save(); | ||||
|         Task Save(); | ||||
|         bool Set(K? key, V? value); | ||||
|     } | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| using System.Collections.Immutable; | ||||
| using HermesSocketLibrary.db; | ||||
| using HermesSocketServer.Models; | ||||
|  | ||||
| @@ -26,7 +27,7 @@ namespace HermesSocketServer.Store | ||||
|                 { "count", "Usage" }, | ||||
|                 { "timespan", "Span" }, | ||||
|             }; | ||||
|             _generator = new GroupSaveSqlGenerator<PolicyMessage>(ctp); | ||||
|             _generator = new GroupSaveSqlGenerator<PolicyMessage>(ctp, _logger); | ||||
|         } | ||||
|  | ||||
|         public override async Task Load() | ||||
| @@ -61,46 +62,53 @@ namespace HermesSocketServer.Store | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public override async Task<bool> Save() | ||||
|         public override async Task Save() | ||||
|         { | ||||
|             int count = 0; | ||||
|             string sql = string.Empty; | ||||
|             ImmutableList<string>? list = null; | ||||
|  | ||||
|             if (_added.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _added.Count; | ||||
|                     sql = _generator.GenerateInsertSql("GroupPermissionPolicy", _added.Select(a => _store[a]), ["id", "userId", "groupId", "path", "count", "timespan"]); | ||||
|                     list = _added.ToImmutableList(); | ||||
|                     _added.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedInsertSql("GroupPermissionPolicy", count, ["id", "userId", "groupId", "path", "count", "timespan"]); | ||||
|  | ||||
|                 _logger.Debug($"GroupPermissionPolicy - Adding {count} rows to database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "userId", "groupId", "path", "count", "timespan"]); | ||||
|             } | ||||
|             if (_modified.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _modified.Count; | ||||
|                     sql = _generator.GenerateUpdateSql("GroupPermissionPolicy", _modified.Select(m => _store[m]), ["id"], ["userId", "groupId", "path", "count", "timespan"]); | ||||
|                     list = _modified.ToImmutableList(); | ||||
|                     _modified.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedUpdateSql("GroupPermissionPolicy", count, ["id"], ["userId", "groupId", "path", "count", "timespan"]); | ||||
|  | ||||
|                 _logger.Debug($"GroupPermissionPolicy - Modifying {count} rows in database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "userId", "groupId", "path", "count", "timespan"]); | ||||
|             } | ||||
|             if (_deleted.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _deleted.Count; | ||||
|                     sql = _generator.GenerateDeleteSql("GroupPermissionPolicy", _deleted, ["id"]); | ||||
|                     list = _deleted.ToImmutableList(); | ||||
|                     _deleted.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedDeleteSql("GroupPermissionPolicy", count, ["id"]); | ||||
|  | ||||
|                 _logger.Debug($"GroupPermissionPolicy - Deleting {count} rows from database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, list, ["id"]); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| using System.Collections.Immutable; | ||||
| using HermesSocketLibrary.db; | ||||
| using HermesSocketServer.Models; | ||||
|  | ||||
| @@ -23,7 +24,7 @@ namespace HermesSocketServer.Store | ||||
|                 { "role", "Role" }, | ||||
|                 { "ttsDefaultVoice", "DefaultVoice" } | ||||
|             }; | ||||
|             _generator = new GroupSaveSqlGenerator<User>(ctp); | ||||
|             _generator = new GroupSaveSqlGenerator<User>(ctp, _logger); | ||||
|         } | ||||
|  | ||||
|         public override async Task Load() | ||||
| @@ -56,45 +57,53 @@ namespace HermesSocketServer.Store | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public override async Task<bool> Save() | ||||
|         public override async Task Save() | ||||
|         { | ||||
|             int count = 0; | ||||
|             string sql = string.Empty; | ||||
|             ImmutableList<string>? list = null; | ||||
|  | ||||
|             if (_added.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _added.Count; | ||||
|                     sql = _generator.GenerateInsertSql("User", _added.Select(a => _store[a]), ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|                     list = _added.ToImmutableList(); | ||||
|                     _added.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedInsertSql("User", count, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Adding {count} rows to database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|             } | ||||
|             if (_modified.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _modified.Count; | ||||
|                     sql = _generator.GenerateUpdateSql("User", _modified.Select(m => _store[m]), ["id"], ["name", "email", "role", "ttsDefaultVoice"]); | ||||
|                     list = _modified.ToImmutableList(); | ||||
|                     _modified.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedUpdateSql("User", count, ["id"], ["name", "email", "role", "ttsDefaultVoice"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Modifying {count} rows in database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|             } | ||||
|             if (_deleted.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _deleted.Count; | ||||
|                     sql = _generator.GenerateDeleteSql("User", _deleted, ["id"]); | ||||
|                     list = _deleted.ToImmutableList(); | ||||
|                     _deleted.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedDeleteSql("User", count, ["id"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Deleting {count} rows from database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, list, ["id"]); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,3 +1,4 @@ | ||||
| using System.Collections.Immutable; | ||||
| using HermesSocketLibrary.db; | ||||
| using HermesSocketServer.Models; | ||||
| using HermesSocketServer.Validators; | ||||
| @@ -25,7 +26,7 @@ namespace HermesSocketServer.Store | ||||
|                 { "id", "Id" }, | ||||
|                 { "name", "Name" } | ||||
|             }; | ||||
|             _generator = new GroupSaveSqlGenerator<Voice>(ctp); | ||||
|             _generator = new GroupSaveSqlGenerator<Voice>(ctp, _logger); | ||||
|         } | ||||
|  | ||||
|         public override async Task Load() | ||||
| @@ -58,46 +59,53 @@ namespace HermesSocketServer.Store | ||||
|         { | ||||
|         } | ||||
|  | ||||
|         public override async Task<bool> Save() | ||||
|         public override async Task Save() | ||||
|         { | ||||
|             int count = 0; | ||||
|             string sql = string.Empty; | ||||
|             ImmutableList<string>? list = null; | ||||
|  | ||||
|             if (_added.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _added.Count; | ||||
|                     sql = _generator.GenerateInsertSql("TtsVoice", _added.Select(a => _store[a]), ["id", "name"]); | ||||
|                     list = _added.ToImmutableList(); | ||||
|                     _added.Clear(); | ||||
|                 } | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedInsertSql("TtsVoice", count, ["id", "name"]); | ||||
|  | ||||
|                _logger.Debug($"TtsVoice - Adding {count} rows to database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 _logger.Debug($"User - Adding {count} rows to database: {sql}"); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|             } | ||||
|             if (_modified.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _modified.Count; | ||||
|                     sql = _generator.GenerateUpdateSql("TtsVoice", _modified.Select(m => _store[m]), ["id"], ["name"]); | ||||
|                     list = _modified.ToImmutableList(); | ||||
|                     _modified.Clear(); | ||||
|                 } | ||||
|                 _logger.Debug($"TtsVoice - Modifying {count} rows in database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedUpdateSql("TtsVoice", count, ["id"], ["name"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Modifying {count} rows in database: {sql}"); | ||||
|                 var values = list.Select(id => _store[id]).Where(v => v != null); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, values, ["id", "name", "email", "role", "ttsDefaultVoice"]); | ||||
|             } | ||||
|             if (_deleted.Any()) | ||||
|             { | ||||
|                 lock (_lock) | ||||
|                 { | ||||
|                     count = _deleted.Count; | ||||
|                     sql = _generator.GenerateDeleteSql("TtsVoice", _deleted, ["id"]); | ||||
|                     list = _deleted.ToImmutableList(); | ||||
|                     _deleted.Clear(); | ||||
|                 } | ||||
|                 _logger.Debug($"TtsVoice - Deleting {count} rows from database: {sql}"); | ||||
|                 await _database.ExecuteScalarTransaction(sql); | ||||
|                 count = list.Count; | ||||
|                 sql = _generator.GeneratePreparedDeleteSql("TtsVoice", count, ["id"]); | ||||
|  | ||||
|                 _logger.Debug($"User - Deleting {count} rows from database: {sql}"); | ||||
|                 await _generator.DoPreparedStatement(_database, sql, list, ["id"]); | ||||
|             } | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user