New SqlDatabase functions

This commit is contained in:
2023-11-07 10:13:22 +02:00
parent 692f3d8f8c
commit 1f0e6516fd
4 changed files with 215 additions and 56 deletions

View File

@@ -85,7 +85,7 @@ public class Boot
await commandServiceHandler.InstallCommandsAsync();
Config._DiscordBotClient = this;
Config.DiscordBotClient = this;
while (!isReady) ;
}

View File

@@ -13,9 +13,9 @@ public class Config
public static Logger Logger;
public static SettingsDictionary<string, string> AppSettings;
internal static Boot? _DiscordBotClient;
internal static Boot? DiscordBotClient;
public static Boot? DiscordBot => _DiscordBotClient;
public static Boot? DiscordBot => DiscordBotClient;
public static async Task Initialize()
{

View File

@@ -9,7 +9,7 @@ namespace PluginManager.Database;
public class SqlDatabase
{
private readonly SQLiteConnection Connection;
private readonly SQLiteConnection _connection;
/// <summary>
/// Initialize a SQL connection by specifing its private path
@@ -22,7 +22,7 @@ public class SqlDatabase
if (!File.Exists(fileName))
SQLiteConnection.CreateFile(fileName);
var connectionString = $"URI=file:{fileName}";
Connection = new SQLiteConnection(connectionString);
_connection = new SQLiteConnection(connectionString);
}
@@ -32,7 +32,7 @@ public class SqlDatabase
/// <returns></returns>
public async Task Open()
{
await Connection.OpenAsync();
await _connection.OpenAsync();
}
/// <summary>
@@ -55,7 +55,7 @@ public class SqlDatabase
query += ")";
var command = new SQLiteCommand(query, Connection);
var command = new SQLiteCommand(query, _connection);
await command.ExecuteNonQueryAsync();
}
@@ -79,7 +79,7 @@ public class SqlDatabase
query += ")";
var command = new SQLiteCommand(query, Connection);
var command = new SQLiteCommand(query, _connection);
command.ExecuteNonQuery();
}
@@ -94,7 +94,7 @@ public class SqlDatabase
{
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
var command = new SQLiteCommand(query, Connection);
var command = new SQLiteCommand(query, _connection);
await command.ExecuteNonQueryAsync();
}
@@ -109,7 +109,7 @@ public class SqlDatabase
{
var query = $"DELETE FROM {tableName} WHERE {KeyName} = '{KeyValue}'";
var command = new SQLiteCommand(query, Connection);
var command = new SQLiteCommand(query, _connection);
command.ExecuteNonQuery();
}
@@ -224,7 +224,7 @@ public class SqlDatabase
/// <returns></returns>
public async void Stop()
{
await Connection.CloseAsync();
await _connection.CloseAsync();
}
/// <summary>
@@ -236,7 +236,7 @@ public class SqlDatabase
/// <returns></returns>
public async Task AddColumnsToTableAsync(string tableName, string[] columns, string TYPE = "TEXT")
{
var command = Connection.CreateCommand();
var command = _connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = await command.ExecuteReaderAsync();
var tableColumns = new List<string>();
@@ -260,7 +260,7 @@ public class SqlDatabase
/// <returns></returns>
public void AddColumnsToTable(string tableName, string[] columns, string TYPE = "TEXT")
{
var command = Connection.CreateCommand();
var command = _connection.CreateCommand();
command.CommandText = $"SELECT * FROM {tableName}";
var reader = command.ExecuteReader();
var tableColumns = new List<string>();
@@ -282,7 +282,7 @@ public class SqlDatabase
/// <returns>True if the table exists, false if not</returns>
public async Task<bool> TableExistsAsync(string tableName)
{
var cmd = Connection.CreateCommand();
var cmd = _connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = await cmd.ExecuteScalarAsync();
@@ -298,7 +298,7 @@ public class SqlDatabase
/// <returns>True if the table exists, false if not</returns>
public bool TableExists(string tableName)
{
var cmd = Connection.CreateCommand();
var cmd = _connection.CreateCommand();
cmd.CommandText = $"SELECT name FROM sqlite_master WHERE type='table' AND name='{tableName}'";
var result = cmd.ExecuteScalar();
@@ -315,7 +315,7 @@ public class SqlDatabase
/// <returns></returns>
public async Task CreateTableAsync(string tableName, params string[] columns)
{
var cmd = Connection.CreateCommand();
var cmd = _connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
await cmd.ExecuteNonQueryAsync();
}
@@ -328,7 +328,7 @@ public class SqlDatabase
/// <returns></returns>
public void CreateTable(string tableName, params string[] columns)
{
var cmd = Connection.CreateCommand();
var cmd = _connection.CreateCommand();
cmd.CommandText = $"CREATE TABLE IF NOT EXISTS {tableName} ({string.Join(", ", columns)})";
cmd.ExecuteNonQuery();
}
@@ -340,9 +340,9 @@ public class SqlDatabase
/// <returns>The number of rows that the query modified</returns>
public async Task<int> ExecuteAsync(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
var answer = await command.ExecuteNonQueryAsync();
return answer;
}
@@ -354,9 +354,9 @@ public class SqlDatabase
/// <returns>The number of rows that the query modified</returns>
public int Execute(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
_connection.Open();
var command = new SQLiteCommand(query, _connection);
var r = command.ExecuteNonQuery();
return r;
@@ -369,9 +369,9 @@ public class SqlDatabase
/// <returns>The result is a string that has all values separated by space character</returns>
public async Task<string?> ReadDataAsync(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
var reader = await command.ExecuteReaderAsync();
var values = new object[reader.FieldCount];
@@ -391,9 +391,9 @@ public class SqlDatabase
/// <returns>The result is a string that has all values separated by space character</returns>
public string? ReadData(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
_connection.Open();
var command = new SQLiteCommand(query, _connection);
var reader = command.ExecuteReader();
var values = new object[reader.FieldCount];
@@ -413,9 +413,9 @@ public class SqlDatabase
/// <returns>The first row as separated items</returns>
public async Task<object[]?> ReadDataArrayAsync(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
var reader = await command.ExecuteReaderAsync();
var values = new object[reader.FieldCount];
@@ -436,9 +436,9 @@ public class SqlDatabase
/// <returns>The first row as separated items</returns>
public object[]? ReadDataArray(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
Connection.Open();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
_connection.Open();
var command = new SQLiteCommand(query, _connection);
var reader = command.ExecuteReader();
var values = new object[reader.FieldCount];
@@ -459,9 +459,9 @@ public class SqlDatabase
/// <returns>A list of string arrays representing the values that the query returns</returns>
public async Task<List<string[]>?> ReadAllRowsAsync(string query)
{
if (!Connection.State.HasFlag(ConnectionState.Open))
await Connection.OpenAsync();
var command = new SQLiteCommand(query, Connection);
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
var reader = await command.ExecuteReaderAsync();
if (!reader.HasRows)
@@ -479,4 +479,163 @@ public class SqlDatabase
return rows;
}
/// <summary>
/// Create a parameter for a query
/// </summary>
/// <param name="name">The name of the parameter</param>
/// <param name="value">The value of the parameter</param>
/// <returns>The SQLiteParameter that has the name, value and DBType set according to your inputs</returns>
private SQLiteParameter? CreateParameter(string name, object value)
{
var parameter = new SQLiteParameter(name);
parameter.Value = value;
if (value is string)
parameter.DbType = DbType.String;
else if (value is int)
parameter.DbType = DbType.Int32;
else if (value is long)
parameter.DbType = DbType.Int64;
else if (value is float)
parameter.DbType = DbType.Single;
else if (value is double)
parameter.DbType = DbType.Double;
else if (value is bool)
parameter.DbType = DbType.Boolean;
else if (value is DateTime)
parameter.DbType = DbType.DateTime;
else if (value is byte[])
parameter.DbType = DbType.Binary;
else if (value is Guid)
parameter.DbType = DbType.Guid;
else if (value is decimal)
parameter.DbType = DbType.Decimal;
else if (value is TimeSpan)
parameter.DbType = DbType.Time;
else if (value is DateTimeOffset)
parameter.DbType = DbType.DateTimeOffset;
else if (value is ushort)
parameter.DbType = DbType.UInt16;
else if (value is uint)
parameter.DbType = DbType.UInt32;
else if (value is ulong)
parameter.DbType = DbType.UInt64;
else if (value is sbyte)
parameter.DbType = DbType.SByte;
else if (value is short)
parameter.DbType = DbType.Int16;
else if (value is byte)
parameter.DbType = DbType.Byte;
else if (value is char)
parameter.DbType = DbType.StringFixedLength;
else if (value is char[])
parameter.DbType = DbType.StringFixedLength;
else
return null;
return parameter;
}
/// <summary>
/// Create a parameter for a query. The function automatically detects the type of the value.
/// </summary>
/// <param name="parameterValues">The parameter raw inputs. The Key is name and the Value is the value of the parameter</param>
/// <returns>The SQLiteParameter that has the name, value and DBType set according to your inputs</returns>
private SQLiteParameter? CreateParameter(KeyValuePair<string, object> parameterValues) =>
CreateParameter(parameterValues.Key, parameterValues.Value);
/// <summary>
/// Execute a query with parameters
/// </summary>
/// <param name="query">The query to execute</param>
/// <param name="parameters">The parameters of the query</param>
/// <returns>The number of rows that the query modified in the database</returns>
public async Task<int> ExecuteNonQueryAsync(string query, params KeyValuePair<string, object>[] parameters)
{
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
foreach (var parameter in parameters)
{
var p = CreateParameter(parameter);
if (p is not null)
command.Parameters.Add(p);
}
return await command.ExecuteNonQueryAsync();
}
/// <summary>
/// Execute a query with parameters that returns a specific type of object. The function will return the first row of the result transformed into the specified type.
/// </summary>
/// <param name="query">The query to execute</param>
/// <param name="convertor">The convertor function that will convert each row of the response into an object of <typeparamref name="T"/></param>
/// <param name="parameters">The parameters of the query</param>
/// <typeparam name="T">The return object type</typeparam>
/// <returns>An object of type T that represents the output of the convertor function based on the array of objects that the first row of the result has</returns>
public async Task<T?> ReadObjectOfTypeAsync<T> (string query, Func<object[], T> convertor, params KeyValuePair<string, object>[] parameters)
{
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
foreach (var parameter in parameters)
{
var p = CreateParameter(parameter);
if (p is not null)
command.Parameters.Add(p);
}
var reader = await command.ExecuteReaderAsync();
var values = new object[reader.FieldCount];
if (reader.Read())
{
reader.GetValues(values);
return convertor(values);
}
return default;
}
/// <summary>
/// Execute a query with parameters that returns a specific type of object. The function will return a list of objects of the specified type.
/// </summary>
/// <param name="query">The query to execute</param>
/// <param name="convertor">The convertor from object[] to T</param>
/// <param name="parameters">The parameters of the query</param>
/// <typeparam name="T">The expected object type</typeparam>
/// <returns>A list of objects of type T that represents each line of the output of the specified query, converted to T</returns>
public async Task<List<T>> ReadListOfTypeAsync<T>(string query, Func<object[], T> convertor,
params KeyValuePair<string, object>[] parameters)
{
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
foreach (var parameter in parameters)
{
var p = CreateParameter(parameter);
if (p is not null)
command.Parameters.Add(p);
}
var reader = await command.ExecuteReaderAsync();
//
if (!reader.HasRows)
return null;
List<T> rows = new();
while (await reader.ReadAsync())
{
var values = new object[reader.FieldCount];
reader.GetValues(values);
rows.Add(convertor(values));
}
return rows;
}
}

View File

@@ -21,13 +21,13 @@ internal class Loader
{
internal Loader(string path, string extension)
{
this.path = path;
this.extension = extension;
this.Path = path;
this.Extension = extension;
}
private string path { get; }
private string extension { get; }
private string Path { get; }
private string Extension { get; }
internal event FileLoadedEventHandler? FileLoaded;
@@ -40,13 +40,13 @@ internal class Loader
List<DBSlashCommand> slashCommands = new();
List<DBCommand> commands = new();
if (!Directory.Exists(path))
if (!Directory.Exists(Path))
{
Directory.CreateDirectory(path);
Directory.CreateDirectory(Path);
return (null, null, null);
}
var files = Directory.GetFiles(path, $"*.{extension}", SearchOption.AllDirectories);
var files = Directory.GetFiles(Path, $"*.{Extension}", SearchOption.AllDirectories);
foreach (var file in files)
{
try