using Npgsql; using NpgsqlTypes; using System.Data; using System.Runtime.InteropServices; using System.Security.Cryptography; using ServerDatabase.Utils; namespace ServerDatabase; public sealed class Database { internal string ConectionString { get { return $"SSL Mode=Disable;Persist Security Info=True;Password={PW};Username={Uname};CommandTimeout={CMD};Database={DB};Host={IP}{CName}"; } } public List Tables { get; } = new() { }; internal string? IP = null, DB = null, Uname = null, PW = null, CName = ""; internal int CMD { get; set; } = 20; public Database(string IpAddress, string Database, string Username, string Password, string? CustomeName = null, int CommandTimeout = 20) { if (!string.IsNullOrWhiteSpace(IpAddress)) IP = IpAddress; if (!string.IsNullOrWhiteSpace(Database)) DB = Database; if (!string.IsNullOrWhiteSpace(Username)) Uname = Username; if (!string.IsNullOrWhiteSpace(Password)) PW = Password; if (!string.IsNullOrWhiteSpace(CustomeName)) CName = $";ApplicationName={CustomeName}"; else CName = ""; VersionsTable = new TableVersions(this); CMD = CommandTimeout; } public void RegisterTables() { foreach (ITable Table in Tables) { foreach (ITableColumn Column in Table.Colums) { VersionsTable.WithColumn(new TableColumn($"{Table.Name}_{Column.Name}") { DefaultValue = Column.ColumnVersion }, string.Empty); } } VersionsTable.UpdateTable(); foreach (ITable Table in Tables) { Table.UpdateTable(); } } public TableVersions VersionsTable { get; } = null!; public void CreateTable(string table, params ITableColumn[] Parameters) { if (string.IsNullOrEmpty(DB) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Uname) || string.IsNullOrEmpty(PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection con = new(ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; string command = $"CREATE TABLE public.{table}("; string key = ""; foreach (ITableColumn column in Parameters) { command += $"{column.Name} {column.GetDatabaseTypeStr()}"; if (column.IsPrimaryKey) key = $"PRIMARY KEY ({column.Name})"; command += " NOT NULL, "; } if (key == "") command = command.Remove(command.Length - 2, 2) + ");"; command += $"{key});"; cmd.CommandText = command; cmd.Prepare(); cmd.ExecuteNonQuery(); con.Close(); } public NpgsqlConnection CreateConnection() { if (string.IsNullOrEmpty(DB) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Uname) || string.IsNullOrEmpty(PW)) throw new Exception("Database conection not fully defined"); return new NpgsqlConnection(ConectionString); } public void ExecuteNonQuery(string command) { if (string.IsNullOrEmpty(DB) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Uname) || string.IsNullOrEmpty(PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection connection = new(ConectionString); connection.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = connection; cmd.CommandText = command; cmd.ExecuteNonQuery(); connection.Close(); } public T Read(string command, Order? order = null, params Parameter[] Parameters) { if (string.IsNullOrEmpty(DB) || string.IsNullOrEmpty(IP) || string.IsNullOrEmpty(Uname) || string.IsNullOrEmpty(PW)) throw new Exception("Database conection not fully defined"); using NpgsqlConnection con = new(ConectionString); con.Open(); using NpgsqlCommand cmd = new(); cmd.Connection = con; string vals = ""; foreach (Parameter param in Parameters) { vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND "; cmd.Parameters.Add(param.PGParameter); } if (command.EndsWith(";")) command = command.Remove(command.Length - 1, 1); if (!string.IsNullOrWhiteSpace(vals)) vals = vals.Remove(vals.Length - 5, 5); if (!string.IsNullOrWhiteSpace(vals) && command.EndsWith("WHERE")) command += $" {vals}"; if (order is not null) command += $" ORDER BY {order.Type} "; if (order is not null && order.Assending) command += "ASC"; else { if (order is not null) command += "DESC"; } command += ";"; cmd.CommandText = command; object? temp = cmd.ExecuteScalar(); con.Close(); if (temp is DBNull || temp is null) return default!; if (typeof(T).IsEnum) return (T?)Enum.Parse(typeof(T), temp.ToString()!)!; if (typeof(T).IsNullableEnum()) return (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, temp.ToString()!)!; return (T?)temp!; } }