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

@@ -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();
}
@@ -163,7 +163,7 @@ public class SqlDatabase
throw new Exception($"Table {tableName} does not exist");
await ExecuteAsync(
$"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
$"UPDATE {tableName} SET {ResultColumnName}='{ResultColumnValue}' WHERE {keyName}='{KeyValue}'");
}
/// <summary>
@@ -224,7 +224,7 @@ public class SqlDatabase
/// <returns></returns>
public async void Stop()
{
await Connection.CloseAsync();
await _connection.CloseAsync();
}
/// <summary>
@@ -236,9 +236,9 @@ 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 reader = await command.ExecuteReaderAsync();
var tableColumns = new List<string>();
for (var i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
@@ -260,9 +260,9 @@ 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 reader = command.ExecuteReader();
var tableColumns = new List<string>();
for (var i = 0; i < reader.FieldCount; i++)
tableColumns.Add(reader.GetName(i));
@@ -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,10 +340,10 @@ 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);
var answer = await command.ExecuteNonQueryAsync();
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
var answer = await command.ExecuteNonQueryAsync();
return answer;
}
@@ -354,10 +354,10 @@ 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);
var r = command.ExecuteNonQuery();
if (!_connection.State.HasFlag(ConnectionState.Open))
_connection.Open();
var command = new SQLiteCommand(query, _connection);
var r = command.ExecuteNonQuery();
return r;
}
@@ -369,10 +369,10 @@ 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);
var reader = await command.ExecuteReaderAsync();
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];
if (reader.Read())
@@ -391,10 +391,10 @@ 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);
var reader = command.ExecuteReader();
if (!_connection.State.HasFlag(ConnectionState.Open))
_connection.Open();
var command = new SQLiteCommand(query, _connection);
var reader = command.ExecuteReader();
var values = new object[reader.FieldCount];
if (reader.Read())
@@ -413,10 +413,10 @@ 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);
var reader = await command.ExecuteReaderAsync();
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];
if (reader.Read())
@@ -436,10 +436,10 @@ 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);
var reader = command.ExecuteReader();
if (!_connection.State.HasFlag(ConnectionState.Open))
_connection.Open();
var command = new SQLiteCommand(query, _connection);
var reader = command.ExecuteReader();
var values = new object[reader.FieldCount];
if (reader.Read())
@@ -459,10 +459,10 @@ 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);
var reader = await command.ExecuteReaderAsync();
if (!_connection.State.HasFlag(ConnectionState.Open))
await _connection.OpenAsync();
var command = new SQLiteCommand(query, _connection);
var reader = await command.ExecuteReaderAsync();
if (!reader.HasRows)
return null;
@@ -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;
}
}