using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; namespace BantFlags.Data.Database { /// /// Functions for interacting with the database. /// public partial class DatabaseService { private MySqlConnectionPool ConnectionPool { get; } private string Flags { get; set; } private HashSet FlagsHash { get; set; } public DatabaseService(DatabaseServiceConfig dbConfig) { ConnectionPool = new MySqlConnectionPool(dbConfig.ConnectionString, dbConfig.PoolSize); var flags = GetFlags().Result; // It's okay to error here since it's only initialised at startup. Flags = string.Join("\n", flags); FlagsHash = flags.ToHashSet(); } public string FlagList() => Flags; public HashSet KnownFlags() => FlagsHash; public async Task UpdateKnownFlags() { var flags = await GetFlags(); Flags = string.Join("\n", flags); FlagsHash = flags.ToHashSet(); } public async Task DeleteFlagsAsync(List flags) { using var rentedConnection = await ConnectionPool.RentConnectionAsync(); using var query = rentedConnection.Object.UseStoredProcedure("delete_flag"); flags.ForEach(async f => await query.SetParam("@flag", f.Name) .ExecuteNonQueryAsync(reuse: true)); return; } public async Task RenameFlagsAsync(List flags) { using var rentedConnection = await ConnectionPool.RentConnectionAsync(); using var query = rentedConnection.Object.UseStoredProcedure("rename_flag"); flags.ForEach(async flag => await query.SetParam("@old", flag.Name) .SetParam("@new", flag.NewName) .ExecuteNonQueryAsync(reuse: true)); } public async Task InsertPost(FlagModel post) { using (var rentedConnection = await ConnectionPool.RentConnectionAsync()) { await rentedConnection.Object.UseStoredProcedure("insert_post") .SetParam("@post_nr", post.PostNumber) .SetParam("@board", post.Board) .ExecuteNonQueryAsync(); using (var query = rentedConnection.Object.UseStoredProcedure("insert_post_flags")) { query.SetParam("@post_nr", post.PostNumber); post.Flags.ForEach(async f => await query.SetParam("@flag", f) .ExecuteNonQueryAsync(reuse: true)); } } return; } /// /// Returns all of the flags that we support. /// public async Task> GetFlags() { using var rentedConnected = await ConnectionPool.RentConnectionAsync(); DataTable table = await rentedConnected.Object.CreateQuery("SELECT flags.flag FROM flags") .ExecuteTableAsync(); return table.AsEnumerable() .Select(x => x.GetValue("flag")) .ToList(); } public async Task InsertFlagsAsync(List flags) { using var rentedConnection = await ConnectionPool.RentConnectionAsync(); using var query = rentedConnection.Object.UseStoredProcedure("insert_flag"); flags.ForEach(async f => await query.SetParam("@flag", f.Name) .ExecuteNonQueryAsync(reuse: true)); return; } } /// /// Configuration data passed by appsettings. /// public class DatabaseServiceConfig { public string ConnectionString { get; set; } public int PoolSize { get; set; } } }