Add attributes for database objects
This commit is contained in:
parent
d2ee23bdb7
commit
f67999d67c
73
ChaosBot/Attribute/AssemblyController.cs
Normal file
73
ChaosBot/Attribute/AssemblyController.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using ChaosBot.Database;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using NLog;
|
||||||
|
|
||||||
|
namespace ChaosBot.Attribute
|
||||||
|
{
|
||||||
|
public static class AssemblyController
|
||||||
|
{
|
||||||
|
private static Logger _logger = Program._logger;
|
||||||
|
public static void Register()
|
||||||
|
{
|
||||||
|
Assembly dbEntityAssembly = Assembly.GetAssembly(typeof(DBEntity));
|
||||||
|
if (dbEntityAssembly != null)
|
||||||
|
{
|
||||||
|
foreach (Type type in dbEntityAssembly.GetTypes())
|
||||||
|
{
|
||||||
|
if (type.GetCustomAttributes(typeof(DBEntity), true).Length > 0)
|
||||||
|
{
|
||||||
|
// type == all classes that have [DBEntity(...)]
|
||||||
|
|
||||||
|
// Get a reference to the attribute
|
||||||
|
DBEntity dbEntity = type.GetCustomAttributes(typeof(DBEntity)).Cast<DBEntity>().First();
|
||||||
|
|
||||||
|
string table = dbEntity.Table;
|
||||||
|
// TODO: Generate this in one go instead of many separate commands
|
||||||
|
Controller.RawQuery($"CREATE TABLE IF NOT EXISTS {table} (id INTEGER NOT NULL CONSTRAINT {table}_pk PRIMARY KEY AUTOINCREMENT)");
|
||||||
|
|
||||||
|
foreach (MethodInfo field in type.GetMethods())
|
||||||
|
{
|
||||||
|
if (field.Name.StartsWith("get_"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// TODO: Use an attribute to detect primary autoincrement key
|
||||||
|
if (field.Name == "id")
|
||||||
|
{
|
||||||
|
Controller.RawQuery($"CREATE UNIQUE INDEX {table}_id_uindex ON {table} (id)", false, true);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
string fieldname = field.Name.Substring(4);
|
||||||
|
string fieldType = DBEntity.DataTypes.GetValueOrDefault(field.ReturnType).ToString();
|
||||||
|
string fieldModifiers = null;
|
||||||
|
|
||||||
|
string query = $"ALTER TABLE {table} ADD COLUMN {fieldname} {fieldType} {fieldModifiers}";
|
||||||
|
Controller.RawQuery(query, false, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (ex is SqliteException sqliteException)
|
||||||
|
{
|
||||||
|
if (!sqliteException.Message.Contains("duplicate column name"))
|
||||||
|
{
|
||||||
|
_logger.Fatal($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.Error($"AssemblyController.Register: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
ChaosBot/Attribute/DBEntity.cs
Normal file
40
ChaosBot/Attribute/DBEntity.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
|
||||||
|
namespace ChaosBot.Attribute
|
||||||
|
{
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class DBEntity : System.Attribute
|
||||||
|
{
|
||||||
|
public readonly string Table;
|
||||||
|
|
||||||
|
public static readonly Dictionary<Type, SqliteType> DataTypes = new Dictionary<Type, SqliteType>
|
||||||
|
{
|
||||||
|
{typeof(bool), SqliteType.Integer},
|
||||||
|
{typeof(byte), SqliteType.Integer},
|
||||||
|
{typeof(byte[]), SqliteType.Blob},
|
||||||
|
{typeof(char), SqliteType.Text},
|
||||||
|
{typeof(DateTime), SqliteType.Text},
|
||||||
|
{typeof(DateTimeOffset), SqliteType.Text},
|
||||||
|
{typeof(Decimal), SqliteType.Text},
|
||||||
|
{typeof(Double), SqliteType.Real},
|
||||||
|
{typeof(Guid), SqliteType.Text},
|
||||||
|
{typeof(Int16), SqliteType.Integer},
|
||||||
|
{typeof(Int32), SqliteType.Integer},
|
||||||
|
{typeof(Int64), SqliteType.Integer},
|
||||||
|
{typeof(SByte), SqliteType.Integer},
|
||||||
|
{typeof(Single), SqliteType.Real},
|
||||||
|
{typeof(String), SqliteType.Text},
|
||||||
|
{typeof(TimeSpan), SqliteType.Text},
|
||||||
|
{typeof(UInt16), SqliteType.Integer},
|
||||||
|
{typeof(UInt32), SqliteType.Integer},
|
||||||
|
{typeof(UInt64), SqliteType.Integer}
|
||||||
|
};
|
||||||
|
|
||||||
|
public DBEntity(string table)
|
||||||
|
{
|
||||||
|
this.Table = table;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,7 +15,7 @@ namespace ChaosBot.Database
|
|||||||
static SqliteConnection _conn = new SqliteConnection($"Data Source={System.IO.Directory.GetCurrentDirectory()}/{Program.Cfg.GetValue<string>("Bot:Database")}");
|
static SqliteConnection _conn = new SqliteConnection($"Data Source={System.IO.Directory.GetCurrentDirectory()}/{Program.Cfg.GetValue<string>("Bot:Database")}");
|
||||||
private static Logger _logger = Program._logger;
|
private static Logger _logger = Program._logger;
|
||||||
|
|
||||||
public static DataTable RawQuery(string query)
|
public static DataTable RawQuery(string query, bool readOutput = true, bool throwError = false)
|
||||||
{
|
{
|
||||||
DataTable dt = new DataTable();
|
DataTable dt = new DataTable();
|
||||||
|
|
||||||
@ -27,15 +27,27 @@ namespace ChaosBot.Database
|
|||||||
|
|
||||||
SqliteCommand cmd = _conn.CreateCommand();
|
SqliteCommand cmd = _conn.CreateCommand();
|
||||||
cmd.CommandText = query;
|
cmd.CommandText = query;
|
||||||
SqliteDataReader executeReader = cmd.ExecuteReader(CommandBehavior.SingleResult);
|
|
||||||
|
if (readOutput)
|
||||||
dt.Load(executeReader);
|
{
|
||||||
|
SqliteDataReader executeReader = cmd.ExecuteReader(CommandBehavior.SingleResult);
|
||||||
|
dt.Load(executeReader);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
_conn.Close();
|
_conn.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
if (throwError)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
_logger.Fatal($"Controllers.DBWork.RawQuery: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
_logger.Fatal($"Controllers.DBWork.RawQuery: Exception [{ex}] thrown, <[{ex.Message}]>.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
|
using ChaosBot.Attribute;
|
||||||
|
|
||||||
namespace ChaosBot.Database.Entity
|
namespace ChaosBot.Database.Entity
|
||||||
{
|
{
|
||||||
|
[DBEntity("RaffleTable")]
|
||||||
public class Raffle
|
public class Raffle
|
||||||
{
|
{
|
||||||
public int id { get; }
|
public int id { get; }
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
using NLog;
|
using NLog;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
using ChaosBot.Discord;
|
using ChaosBot.Discord;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using ChaosBot.Attribute;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
|
|
||||||
|
|
||||||
@ -34,6 +36,12 @@ namespace ChaosBot
|
|||||||
* Initialize the _logger for logging purposes
|
* Initialize the _logger for logging purposes
|
||||||
*/
|
*/
|
||||||
_logger = Logging.GenLog();
|
_logger = Logging.GenLog();
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt to load our custom assemblies
|
||||||
|
*/
|
||||||
|
AssemblyController.Register();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the Discord Client and Login
|
* Initialize the Discord Client and Login
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user