using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using Microsoft.Data.Sqlite; using Microsoft.Extensions.Configuration; using Microsoft.VisualBasic; using NLog; namespace ChaosBot.Database { public static class Controller { static SqliteConnection _conn = new SqliteConnection($"Data Source={System.IO.Directory.GetCurrentDirectory()}/{Program.Cfg.GetValue("Bot:Database")}"); private static Logger _logger = Program._logger; public static DataTable RawQuery(string query) { DataTable dt = new DataTable(); try { using (_conn) { _conn.Open(); SqliteCommand cmd = _conn.CreateCommand(); cmd.CommandText = query; SqliteDataReader executeReader = cmd.ExecuteReader(CommandBehavior.SingleResult); dt.Load(executeReader); _conn.Close(); } } catch (Exception ex) { _logger.Fatal($"Controllers.DBWork.RawQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); } return dt; } public static void InsertQuery(string table, Dictionary parameters) { try { using (_conn) { _conn.Open(); SqliteCommand cmd = _conn.CreateCommand(); StringBuilder commandText = new StringBuilder(); commandText.Append("INSERT INTO "); commandText.Append(table); commandText.Append(" ("); foreach (string key in parameters.Keys) { commandText.Append($"{key}, "); } commandText.Remove(commandText.Length - 2, 2); commandText.Append(") VALUES ("); foreach (string key in parameters.Keys) { commandText.Append($"@{key},"); } commandText.Remove(commandText.Length - 1, 1); commandText.Append(")"); cmd.CommandText = commandText.ToString(); foreach (string key in parameters.Keys) { cmd.Parameters.AddWithValue($"@{key}", parameters.GetValueOrDefault(key)); } cmd.Prepare(); cmd.ExecuteNonQuery(); _conn.Close(); } } catch (Exception ex) { _logger.Fatal($"Controllers.DBWork.RawQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); } } public static int TransactionQuery(List cmds) { SqliteCommand command = _conn.CreateCommand(); SqliteTransaction transaction; _conn.Open(); // Start a local transaction. transaction = _conn.BeginTransaction(); // Must assign both transaction object and connection // to Command object for a pending local transaction command.Connection = _conn; command.Transaction = transaction; try { foreach (var cmd in cmds) { command.CommandText = cmd.CommandText; command.ExecuteNonQuery(); } // Attempt to commit the transaction. transaction.Commit(); _logger.Info($"{cmds.Count} record(s) are written to database."); } catch (Exception ex) { _logger.Warn("Commit Exception Type: {0}", ex.GetType()); _logger.Warn(" Message: {0}", ex.Message); // Attempt to roll back the transaction. try { transaction.Rollback(); } catch (Exception ex2) { // This catch block will handle any errors that may have occurred // on the server that would cause the rollback to fail, such as // a closed connection. _logger.Warn("Rollback Exception Type: {0}", ex2.GetType()); _logger.Warn(" Message: {0}", ex2.Message); } return 0; } _conn.Close(); return cmds.Count; } public static DataTable SelectQuery(string table, string selectColumns = "*", Dictionary filterColumns = null, string orderByKey = null) { DataTable dt = new DataTable(); try { using (_conn) { _conn.Open(); SqliteCommand cmd = _conn.CreateCommand(); string filter = null; if (filterColumns != null) { List filterList = new List(); foreach (string key in filterColumns.Keys) { filterList.Add($"{key} = @{key}"); } filter = $"WHERE {Strings.Join(filterList.ToArray(), " AND ")}"; foreach (string key in filterColumns.Keys) { cmd.Parameters.AddWithValue($@"{key}", filterColumns.GetValueOrDefault(key)); } } string order = null; if (orderByKey != null) { order = $"ORDER BY {orderByKey}"; } string query = $"SELECT {selectColumns} FROM {table} {filter} {order}"; cmd.CommandText = query; cmd.Prepare(); SqliteDataReader executeReader = cmd.ExecuteReader(); dt.Load(executeReader); _conn.Close(); } } catch (Exception ex) { _logger.Fatal($"Controllers.DBWork.RawQuery: Exception [{ex}] thrown, <[{ex.Message}]>."); } return dt; } } }