Init
This commit is contained in:
parent
abff28d1a0
commit
de8884aaf4
15
.gitignore
vendored
15
.gitignore
vendored
@ -8,6 +8,8 @@
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
.idea/**/.idea/**
|
||||
.idea/**/.idea/
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
@ -77,3 +79,16 @@ fabric.properties
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
25
Database.sln
Executable file
25
Database.sln
Executable file
@ -0,0 +1,25 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.2.32427.441
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ServerDatabase", "Database\ServerDatabase.csproj", "{108C054C-5FA5-4D16-9F48-B6836B1734EB}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{108C054C-5FA5-4D16-9F48-B6836B1734EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{108C054C-5FA5-4D16-9F48-B6836B1734EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{108C054C-5FA5-4D16-9F48-B6836B1734EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{108C054C-5FA5-4D16-9F48-B6836B1734EB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {D50765B5-8753-440E-A312-24DF78B78E73}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
129
Database/Database.cs
Executable file
129
Database/Database.cs
Executable file
@ -0,0 +1,129 @@
|
||||
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<ITable> 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<long>($"{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<T>(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!;
|
||||
}
|
||||
}
|
30
Database/Ext.cs
Executable file
30
Database/Ext.cs
Executable file
@ -0,0 +1,30 @@
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
internal static class Ext
|
||||
{
|
||||
internal static bool IsNullableEnum(this Type t)
|
||||
{
|
||||
Type u = Nullable.GetUnderlyingType(t)!;
|
||||
return (u != null) && u.IsEnum;
|
||||
}
|
||||
|
||||
public static OutputType[] Cast<InputType, OutputType>(InputType f)
|
||||
{
|
||||
Array inputArray_in = (Array)(object)f;
|
||||
var aRange = Partitioner.Create(0, inputArray_in.Length);
|
||||
OutputType[] aResult = new OutputType[inputArray_in.Length];
|
||||
|
||||
Parallel.ForEach(aRange, (r) =>
|
||||
{
|
||||
for (int i = r.Item1; i < r.Item2; i++)
|
||||
{
|
||||
aResult[i] = (OutputType)(inputArray_in.GetValue(i));
|
||||
}
|
||||
});
|
||||
|
||||
return aResult;
|
||||
}
|
||||
|
||||
}
|
12
Database/ITable.cs
Normal file
12
Database/ITable.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using ServerDatabase.Utils;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public interface ITable
|
||||
{
|
||||
public void UpdateTable();
|
||||
public IReadOnlyList<ITableColumn> Colums { get; }
|
||||
public string Name { get; set; }
|
||||
public Database DatabaseHandler { get; set; }
|
||||
public void AddColumn(ITableColumn Column, string name);
|
||||
}
|
11
Database/Order.cs
Executable file
11
Database/Order.cs
Executable file
@ -0,0 +1,11 @@
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class Order
|
||||
{
|
||||
internal Order()
|
||||
{
|
||||
|
||||
}
|
||||
public bool Assending { get; init; } = default!;
|
||||
public string Type { get; init; } = default!;
|
||||
}
|
34
Database/ServerDatabase.csproj
Executable file
34
Database/ServerDatabase.csproj
Executable file
@ -0,0 +1,34 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<FileVersion>1.0.0.0</FileVersion>
|
||||
<Authors>JacobTech</Authors>
|
||||
<Company>JacobTech, LLC</Company>
|
||||
<Description>A Database class to handle database interactions</Description>
|
||||
<IncludeSymbols>False</IncludeSymbols>
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageTags>Postgresql;sql</PackageTags>
|
||||
<Title>Server Database</Title>
|
||||
<Version>2.8.1</Version>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.6.0" />
|
||||
<PackageReference Include="Npgsql" Version="7.0.0" />
|
||||
<PackageReference Include="ServerDatabase.Utils" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CustomActionsAfterPublish" AfterTargets="Pack">
|
||||
<Message Text="Actions AfterPublish: $(PackageId).$(PackageVersion).nupkg" Importance="high" />
|
||||
<Exec Command="nuget push -Source https://nuget.jacobtech.com/v3/index.json bin/Release/$(PackageId).$(PackageVersion).nupkg" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
463
Database/Table.cs
Normal file
463
Database/Table.cs
Normal file
@ -0,0 +1,463 @@
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using Npgsql;
|
||||
using ServerDatabase.Utils;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class Table<TRow> : ITable where TRow : class, new()
|
||||
{
|
||||
public Table(string Name, Database DB)
|
||||
{
|
||||
if (Name == "table_versions") throw new ArgumentException("The table name 'table_versions' is not allowed", nameof(Name));
|
||||
this.Name = Name;
|
||||
DatabaseHandler = DB;
|
||||
}
|
||||
|
||||
internal Table(Database DB)
|
||||
{
|
||||
this.Name = "table_versions";
|
||||
DatabaseHandler = DB;
|
||||
}
|
||||
|
||||
public Table<TRow> WithColumn(ITableColumn Column, string name)
|
||||
{
|
||||
Colums_.Add(Column);
|
||||
colnamesraw.Add(Column.Name, name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void AddColumn(ITableColumn Column, string name)
|
||||
{
|
||||
colnamesraw.Add(Column.Name, name);
|
||||
Colums_.Add(Column);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public IReadOnlyList<ITableColumn> GetMissingColumns(out IReadOnlyList<ITableColumn> UpdatedColumns)
|
||||
{
|
||||
List<ITableColumn> coll = new(Colums_);
|
||||
List<ITableColumn> col = new(Colums_);
|
||||
foreach (DataRow row in DatabaseHandler.CreateConnection().GetSchema("Columns", new[] { DatabaseHandler.DB, null, Name }).Rows)
|
||||
{
|
||||
string name = row.Field<string>("COLUMN_NAME")!,
|
||||
ty = row.Field<string>("DATA_TYPE")!;
|
||||
IEnumerable<ITableColumn> t = Colums_.Where(s => s.Name == name);
|
||||
if (t.Any())
|
||||
{
|
||||
col.Remove(t.First());
|
||||
if (t.First()!.GetDatabaseTypeStr() == ty) coll.Remove(t.First());
|
||||
}
|
||||
}
|
||||
|
||||
UpdatedColumns = coll;
|
||||
return col.AsReadOnly();
|
||||
}
|
||||
|
||||
public void UpdateTable()
|
||||
{
|
||||
Console.WriteLine("Updating Table: {0}", Name);
|
||||
IReadOnlyList<ITableColumn> m = GetMissingColumns(out IReadOnlyList<ITableColumn> n);
|
||||
if (m.Any())
|
||||
{
|
||||
if (DatabaseHandler.Read<long>(
|
||||
$"SELECT COUNT(table_name) FROM information_schema.tables WHERE table_schema LIKE 'public' AND table_type LIKE 'BASE TABLE' AND table_name = '{Name}';") ==
|
||||
0)
|
||||
{
|
||||
Create();
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (ITableColumn col in m)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (col.IsPrimaryKey) throw new Exception($"DELETE THE TABLE '{Name}' TO FIX TABLE GENERATION");
|
||||
string sql = $"ALTER TABLE IF EXISTS public.{Name} ADD COLUMN {col.Name} {col.GetDatabaseTypeStr()}";
|
||||
sql += " NOT NULL";
|
||||
if (col.GetDefaultStr() is not null) sql += $" DEFAULT {col.GetDefaultStr()}";
|
||||
sql += ";";
|
||||
DatabaseHandler.ExecuteNonQuery(sql);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Posible fail to set default for public.{0}.{1}", Name, col.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n.Any())
|
||||
{
|
||||
foreach (ITableColumn col in n)
|
||||
{
|
||||
string sql = $"ALTER TABLE public.{Name} ALTER COLUMN {col.Name} TYPE {col.GetDatabaseTypeStr()};";
|
||||
|
||||
DatabaseHandler.ExecuteNonQuery(sql);
|
||||
if (col.GetDefaultStr() is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
sql = $"ALTER TABLE IF EXISTS public.{Name} ALTER COLUMN {col.Name} SET DEFAULT {col.GetDefaultStr()};";
|
||||
DatabaseHandler.ExecuteNonQuery(sql);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine("Failed to set default for public.{0}.{1}\nSQL: {2}", Name, col.Name, sql);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Table<TRow> DropColumn<TType>(TableColumn<TType> Column) where TType : notnull
|
||||
{
|
||||
Colums_.Remove(Column);
|
||||
return this;
|
||||
}
|
||||
|
||||
private Dictionary<string, string> colnamesraw = new();
|
||||
|
||||
private List<ITableColumn> Colums_ { get; set; } = new();
|
||||
|
||||
public IReadOnlyList<ITableColumn> Colums => Colums_.AsReadOnly();
|
||||
|
||||
public string Name { get; set; } = default!;
|
||||
|
||||
public Database DatabaseHandler { get; set; } = default!;
|
||||
|
||||
public void Insert(params Parameter[] Parameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
con.Open();
|
||||
using NpgsqlCommand cmd = new();
|
||||
cmd.Connection = con;
|
||||
string vals = "";
|
||||
List<ITableColumn> l = new List<ITableColumn>(Colums_);
|
||||
foreach (Parameter param in Parameters)
|
||||
{
|
||||
l.Remove(l.Where(s => s.Name == param.PGParameter.ParameterName).First());
|
||||
vals += "@" + param.PGParameter.ParameterName + ", ";
|
||||
cmd.Parameters.Add(param.PGParameter);
|
||||
}
|
||||
|
||||
foreach (ITableColumn cop in l)
|
||||
{
|
||||
var param = cop.CreateDefaultParameter();
|
||||
vals += "@" + param.PGParameter.ParameterName + ", ";
|
||||
cmd.Parameters.Add(param.PGParameter);
|
||||
}
|
||||
vals = vals.Remove(vals.Length - 2, 2);
|
||||
cmd.CommandText = $"INSERT INTO {Name} ({vals.Replace("@", "")}) VALUES({vals})";
|
||||
cmd.Prepare();
|
||||
cmd.ExecuteNonQuery();
|
||||
con.Close();
|
||||
}
|
||||
|
||||
public void DeleteRow(Parameter Parameter)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
con.Open();
|
||||
using NpgsqlCommand cmd = new();
|
||||
cmd.Connection = con;
|
||||
cmd.Parameters.Add(Parameter.PGParameter);
|
||||
cmd.CommandText = $"DELETE FROM {Name} WHERE {Parameter.PGParameter.ParameterName} IN (@{Parameter.PGParameter.ParameterName});";
|
||||
cmd.Prepare();
|
||||
cmd.ExecuteNonQuery();
|
||||
con.Close();
|
||||
}
|
||||
|
||||
public void Create()
|
||||
{
|
||||
Console.WriteLine("Making Table: {0}", Name);
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
con.Open();
|
||||
using NpgsqlCommand cmd = new();
|
||||
cmd.Connection = con;
|
||||
string command = $"CREATE TABLE public.{Name}(";
|
||||
string key = "";
|
||||
foreach (ITableColumn column in Colums_)
|
||||
{
|
||||
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();
|
||||
DatabaseHandler.ExecuteNonQuery($"ALTER TABLE IF EXISTS public.{Name} OWNER to {DatabaseHandler.Uname}");
|
||||
}
|
||||
|
||||
public bool TryRead<T>(TableColumn<T> column, Order order, [NotNullWhen(true)][MaybeNullWhen(false)]out T result, params Parameter[] Parameters) where T : notnull
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
con.Open();
|
||||
using NpgsqlCommand cmd = new();
|
||||
cmd.Connection = con;
|
||||
string vals = "";
|
||||
string command = $"SELECT {column.Name} FROM {Name} WHERE";
|
||||
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();
|
||||
object? temp = null;
|
||||
try
|
||||
{
|
||||
temp = cmd.ExecuteScalar();
|
||||
}
|
||||
catch
|
||||
{
|
||||
result = default(T);
|
||||
return false;
|
||||
}
|
||||
con.Close();
|
||||
if (temp is DBNull || temp is null)
|
||||
{
|
||||
result = default(T);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof(T).IsEnum)
|
||||
{
|
||||
result = (T)Enum.Parse(typeof(T), temp.ToString()!)!;
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
if (typeof(T).IsNullableEnum())
|
||||
{
|
||||
result = (T?)Enum.Parse(Nullable.GetUnderlyingType(typeof(T))!, temp.ToString()!)!;
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
result = (T)temp!;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool TryReadRow(out TRow row, params Parameter[] Parameters) => TryReadRow(null, out row, Parameters);
|
||||
|
||||
public bool TryReadRow(Order order, out TRow row, params Parameter[] Parameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
string command = $"SELECT * FROM {Name} WHERE";
|
||||
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;
|
||||
NpgsqlDataReader reader = cmd.ExecuteReader();
|
||||
TRow Row = new();
|
||||
reader.Read();
|
||||
bool r = false;
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
r = true;
|
||||
string colname = reader.GetName(i);
|
||||
object? val = null;
|
||||
try
|
||||
{
|
||||
val = reader.GetValue(i);
|
||||
}
|
||||
catch
|
||||
{
|
||||
row = default(TRow);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (colnamesraw.ContainsKey(colname))
|
||||
{
|
||||
if (val is DBNull || val is null)
|
||||
{
|
||||
row = default(TRow);
|
||||
return false;
|
||||
}
|
||||
PropertyInfo? pi = Row.GetType()
|
||||
.GetProperty(colnamesraw[colname]);
|
||||
if (pi is null)
|
||||
{
|
||||
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
|
||||
continue;
|
||||
}
|
||||
pi.SetValue(Row, val, null);
|
||||
}
|
||||
}
|
||||
|
||||
row = Row;
|
||||
return r;
|
||||
}
|
||||
|
||||
public bool TryRead<T>(TableColumn<T> column, [NotNullWhen(true)][MaybeNullWhen(false)]out T result, params Parameter[] Parameters) where T : notnull
|
||||
{
|
||||
return TryRead(column, null!, out result, Parameters);
|
||||
}
|
||||
|
||||
public void Update<Ttype>(TableColumn<Ttype> condiction_column, Ttype condiction_value, params Parameter[] Parameters) where Ttype : notnull
|
||||
{
|
||||
Update(condiction_column, condiction_value, "=", Parameters);
|
||||
}
|
||||
|
||||
public void Update<Ttype>(TableColumn<Ttype> condiction_column, Ttype condiction_value, string Sign, params Parameter[] Parameters) where Ttype : notnull
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.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}, ";
|
||||
cmd.Parameters.Add(param.PGParameter);
|
||||
}
|
||||
vals = vals.Remove(vals.Length - 2, 2);
|
||||
cmd.Parameters.Add(condiction_column.CreateParameter(condiction_value).PGParameter);
|
||||
cmd.CommandText = $"UPDATE {Name} SET {vals} WHERE {condiction_column.Name} {Sign} @{condiction_column.Name};";
|
||||
cmd.Prepare();
|
||||
cmd.ExecuteNonQuery();
|
||||
con.Close();
|
||||
}
|
||||
|
||||
public TRow ReadRow(params Parameter[] Parameters) => ReadRow(null, Parameters);
|
||||
|
||||
public TRow ReadRow(Order order, params Parameter[] Parameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
string command = $"SELECT * FROM {Name} WHERE";
|
||||
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;
|
||||
NpgsqlDataReader reader = cmd.ExecuteReader();
|
||||
TRow Row = new();
|
||||
reader.Read();
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
string colname = reader.GetName(i);
|
||||
object? val = reader.GetValue(i);
|
||||
if (colnamesraw.ContainsKey(colname))
|
||||
{
|
||||
PropertyInfo? pi = Row.GetType()
|
||||
.GetProperty(colnamesraw[colname]);
|
||||
if (pi is null)
|
||||
{
|
||||
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
|
||||
continue;
|
||||
}
|
||||
pi.SetValue(Row, val, null);
|
||||
}
|
||||
}
|
||||
|
||||
return Row;
|
||||
}
|
||||
|
||||
public TRow[] ReadRows(uint NumRows, params Parameter[] Parameters) => ReadRows(NumRows, null, Parameters);
|
||||
|
||||
public TRow[] ReadRows(uint NumRows, Order order, params Parameter[] Parameters)
|
||||
{
|
||||
if (string.IsNullOrEmpty(DatabaseHandler.DB) || string.IsNullOrEmpty(DatabaseHandler.IP) || string.IsNullOrEmpty(DatabaseHandler.Uname) || string.IsNullOrEmpty(DatabaseHandler.PW)) throw new Exception("Database conection not fully defined");
|
||||
using NpgsqlConnection con = new(DatabaseHandler.ConectionString);
|
||||
string command = $"SELECT * FROM {Name} WHERE";
|
||||
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 += $" LIMIT {NumRows};";
|
||||
cmd.CommandText = command;
|
||||
NpgsqlDataReader reader = cmd.ExecuteReader();
|
||||
List<TRow> Rows = new();
|
||||
for (int j = 0; j < NumRows; j++)
|
||||
{
|
||||
if (!reader.Read()) break;
|
||||
for (int i = 0; i < reader.FieldCount; i++)
|
||||
{
|
||||
TRow Row = new();
|
||||
string colname = reader.GetName(i);
|
||||
object? val = reader.GetValue(i);
|
||||
if (colnamesraw.ContainsKey(colname))
|
||||
{
|
||||
PropertyInfo? pi = Row.GetType()
|
||||
.GetProperty(colnamesraw[colname]);
|
||||
if (pi is null)
|
||||
{
|
||||
Console.WriteLine("Could not find row {0}", colnamesraw[colname]);
|
||||
continue;
|
||||
}
|
||||
pi.SetValue(Row, val, null);
|
||||
}
|
||||
Rows.Add(Row);
|
||||
}
|
||||
}
|
||||
|
||||
return Rows.ToArray();
|
||||
}
|
||||
|
||||
public T Read<T>(TableColumn<T> column, params Parameter[] Parameters) where T : notnull
|
||||
{
|
||||
if (Parameters is null) throw new ArgumentNullException(nameof(Parameters));
|
||||
return DatabaseHandler.Read<T>($"SELECT {column.Name} FROM {Name} WHERE", (Order?)null, Parameters);
|
||||
}
|
||||
|
||||
public T Read<T>(TableColumn<T> column, Order order, params Parameter[] Parameters) where T : notnull
|
||||
{
|
||||
if (Parameters is null) throw new ArgumentNullException(nameof(Parameters));
|
||||
return DatabaseHandler.Read<T>($"SELECT {column.Name} FROM {Name} WHERE", order, Parameters);
|
||||
}
|
||||
}
|
299
Database/TableColumn.cs
Normal file
299
Database/TableColumn.cs
Normal file
@ -0,0 +1,299 @@
|
||||
using System.Data;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
using ServerDatabase.Utils;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class TableColumn<Ttype> : ITableColumn where Ttype : notnull
|
||||
{
|
||||
public TableColumn(string Name, bool IsPrimaryKey = false)
|
||||
{
|
||||
this.Name = Name;
|
||||
this.IsPrimaryKey = IsPrimaryKey;
|
||||
}
|
||||
|
||||
public long ColumnVersion { get; set; } = 0;
|
||||
public Order GetDecendingOrder() => new Order() { Assending = false, Type = Name };
|
||||
public Order GetAssendingOrder() => new Order() { Assending = true, Type = Name };
|
||||
|
||||
public Ttype DefaultValue { get; set; }
|
||||
|
||||
public string Name { get; set; } = default!;
|
||||
public Type Type { get; } = typeof(Ttype);
|
||||
public bool IsPrimaryKey { get; set; } = false;
|
||||
public object? GetDefault() => DefaultValue;
|
||||
|
||||
public string? GetDefaultStr()
|
||||
{
|
||||
if (DefaultValue is null) return null;
|
||||
else if (DefaultValue is DateTime) return "CURRENT_DATE";
|
||||
else if (Type.FullName == typeof(string).FullName) return $"'{DefaultValue.ToString()}'::text";
|
||||
else if (Type.IsArray)
|
||||
{
|
||||
Type t = Type.GetElementType();
|
||||
if (t.IsEnum)
|
||||
{
|
||||
t = t.GetEnumUnderlyingType();
|
||||
}
|
||||
if (t.Name == typeof(long).Name) return $"'{{{string.Join(", ", DefaultValue as long[])}}}'::bigint[]";
|
||||
else if (t.Name == typeof(int).Name) return $"'{{{string.Join(", ", DefaultValue as int[])}}}'::integer[]";
|
||||
else if (t.Name == typeof(short).Name)
|
||||
return $"'{{{string.Join(", ", DefaultValue as short[])}}}'::smallint[]";
|
||||
else return null;
|
||||
}
|
||||
else if (Type.IsEnum)
|
||||
{
|
||||
return $"{Convert.ChangeType(DefaultValue, Type.GetEnumUnderlyingType())}";
|
||||
}
|
||||
else
|
||||
{
|
||||
return DefaultValue.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
private object? _defalt = null;
|
||||
|
||||
public Type GetDatabaseType()
|
||||
{
|
||||
if (Type.IsEnum)
|
||||
{
|
||||
return Type.GetEnumUnderlyingType();
|
||||
}
|
||||
|
||||
if (Type.IsNullableEnum())
|
||||
{
|
||||
return Nullable.GetUnderlyingType(Type)!.GetEnumUnderlyingType();
|
||||
}
|
||||
|
||||
if (Type.IsArray)
|
||||
{
|
||||
Type element = Type.GetElementType()!;
|
||||
if (element.IsEnum)
|
||||
{
|
||||
return element.GetEnumUnderlyingType().MakeArrayType();
|
||||
}
|
||||
|
||||
if (element.IsNullableEnum())
|
||||
{
|
||||
return Nullable.GetUnderlyingType(element)!.GetEnumUnderlyingType().MakeArrayType();
|
||||
}
|
||||
}
|
||||
|
||||
return Type;
|
||||
}
|
||||
|
||||
public string GetDatabaseTypeStr()
|
||||
{
|
||||
return typestrmap[GetDatabaseType()];
|
||||
}
|
||||
|
||||
public Parameter CreateDefaultParameter([DisallowNull] string sign = "=") =>
|
||||
CreateParameter(DefaultValue, sign);
|
||||
|
||||
public Parameter CreateParameter([DisallowNull]Ttype Value, [DisallowNull]string sign = "=")
|
||||
{
|
||||
Type t = Value.GetType();
|
||||
Tuple<DbType, NpgsqlDbType>? types;
|
||||
if (t.IsEnum)
|
||||
{
|
||||
t = t.GetEnumUnderlyingType();
|
||||
types = typemap[t];
|
||||
return new()
|
||||
{
|
||||
PGParameter = new NpgsqlParameter(Name, Convert.ChangeType(Value, t))
|
||||
{
|
||||
DbType = types.Item1,
|
||||
NpgsqlDbType = types.Item2
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
}
|
||||
if (t.IsArray)
|
||||
{
|
||||
t = t.GetElementType()!;
|
||||
|
||||
if (t.IsEnum)
|
||||
{
|
||||
t = t.GetEnumUnderlyingType();
|
||||
types = typemap[t.MakeArrayType()];
|
||||
Enum[] tempenum = Ext.Cast<Ttype, Enum>(Value);
|
||||
switch (t.FullName)
|
||||
{
|
||||
case "System.Int64":
|
||||
return new()
|
||||
{
|
||||
PGParameter = new NpgsqlParameter(Name, Array.ConvertAll(tempenum, value => Convert.ToInt64(value)))
|
||||
{
|
||||
DbType = types.Item1,
|
||||
NpgsqlDbType = types.Item2
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
case "System.Int32":
|
||||
return new()
|
||||
{
|
||||
PGParameter = new NpgsqlParameter(Name, Array.ConvertAll(tempenum, value => Convert.ToInt32(value)))
|
||||
{
|
||||
DbType = types.Item1,
|
||||
NpgsqlDbType = types.Item2
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
case "System.Int16":
|
||||
return new()
|
||||
{
|
||||
PGParameter = new NpgsqlParameter(Name, Array.ConvertAll(tempenum, value => Convert.ToInt16(value)))
|
||||
{
|
||||
DbType = types.Item1,
|
||||
NpgsqlDbType = types.Item2
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
t = t.MakeArrayType();
|
||||
types = typemap[t];
|
||||
}
|
||||
/*if (value is null)
|
||||
{
|
||||
t = typeof(Ttype);
|
||||
if (t.IsNullableEnum()) t = Nullable.GetUnderlyingType(t)!.GetEnumUnderlyingType();
|
||||
types = typemap[t];
|
||||
return new()
|
||||
{
|
||||
PGParameter = new(Name, value)
|
||||
{
|
||||
IsNullable = true,
|
||||
Value = DBNull.Value,
|
||||
DbType = types.Item1,
|
||||
NpgsqlDbType = types.Item2
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
}*/
|
||||
types = typemap[t!];
|
||||
if (types is null)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
PGParameter = new(Name, Value)
|
||||
};
|
||||
}
|
||||
return new()
|
||||
{
|
||||
PGParameter = new NpgsqlParameter(Name, Value)
|
||||
{
|
||||
DbType = types.Item1,
|
||||
NpgsqlDbType = types.Item2
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
}
|
||||
|
||||
public Parameter CreateJsonParameter([DisallowNull]Ttype value, [DisallowNull]string sign = "=")
|
||||
{
|
||||
return new()
|
||||
{
|
||||
PGParameter = new NpgsqlParameter(Name, value)
|
||||
{
|
||||
NpgsqlDbType = NpgsqlDbType.Jsonb
|
||||
},
|
||||
Sign = sign
|
||||
};
|
||||
}
|
||||
|
||||
private readonly Dictionary<Type, Tuple<DbType, NpgsqlDbType>?> typemap = new()
|
||||
{
|
||||
{typeof(byte), new(DbType.Byte, NpgsqlDbType.Unknown)},
|
||||
{typeof(sbyte), new(DbType.SByte, NpgsqlDbType.Unknown)},
|
||||
{typeof(short), new(DbType.Int16, NpgsqlDbType.Smallint)},
|
||||
{typeof(ushort), new(DbType.UInt16, NpgsqlDbType.Smallint)},
|
||||
{typeof(int), new(DbType.Int32, NpgsqlDbType.Integer)},
|
||||
{typeof(uint), new(DbType.UInt32, NpgsqlDbType.Integer)},
|
||||
{typeof(long), new(DbType.Int64, NpgsqlDbType.Bigint)},
|
||||
{typeof(ulong), new(DbType.UInt64, NpgsqlDbType.Bigint)},
|
||||
{typeof(float), new(DbType.Single, NpgsqlDbType.Real)},
|
||||
{typeof(double), new(DbType.Double, NpgsqlDbType.Double)},
|
||||
{typeof(decimal), new(DbType.Decimal, NpgsqlDbType.Money)},
|
||||
{typeof(bool), new(DbType.Boolean, NpgsqlDbType.Boolean)},
|
||||
{typeof(string), new(DbType.String, NpgsqlDbType.Text)},
|
||||
{typeof(char), new(DbType.StringFixedLength, NpgsqlDbType.Char)},
|
||||
{typeof(Guid), new(DbType.Guid, NpgsqlDbType.Uuid)},
|
||||
{typeof(DateTime), new(DbType.DateTime, NpgsqlDbType.Date)},
|
||||
{typeof(DateTimeOffset), new(DbType.DateTimeOffset, NpgsqlDbType.TimeTz)},
|
||||
{typeof(byte[]), new(DbType.Binary, NpgsqlDbType.Bytea)},
|
||||
{typeof(byte[][]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Bytea)},
|
||||
{typeof(byte?), new(DbType.Byte, NpgsqlDbType.Unknown)},
|
||||
{typeof(sbyte?), new(DbType.SByte, NpgsqlDbType.Unknown)},
|
||||
{typeof(short?), new(DbType.Int16, NpgsqlDbType.Smallint)},
|
||||
{typeof(ushort?), new(DbType.UInt16, NpgsqlDbType.Smallint)},
|
||||
{typeof(int?), new(DbType.Int32, NpgsqlDbType.Integer)},
|
||||
{typeof(uint?), new(DbType.UInt32, NpgsqlDbType.Integer)},
|
||||
{typeof(long?), new(DbType.Int64, NpgsqlDbType.Bigint)},
|
||||
{typeof(ulong?), new(DbType.UInt64, NpgsqlDbType.Bigint)},
|
||||
{typeof(float?), new(DbType.Single, NpgsqlDbType.Real)},
|
||||
{typeof(double?), new(DbType.Double, NpgsqlDbType.Double)},
|
||||
{typeof(decimal?), new(DbType.Decimal, NpgsqlDbType.Money)},
|
||||
{typeof(bool?), new(DbType.Boolean, NpgsqlDbType.Boolean)},
|
||||
{typeof(char?), new(DbType.StringFixedLength, NpgsqlDbType.Char)},
|
||||
{typeof(Guid?), new(DbType.Guid, NpgsqlDbType.Uuid)},
|
||||
{typeof(DateTime?), new(DbType.DateTime, NpgsqlDbType.Uuid)},
|
||||
{typeof(DateTimeOffset?), new(DbType.DateTimeOffset, NpgsqlDbType.TimeTz)},
|
||||
{typeof(string[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Text)},
|
||||
{typeof(long[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Bigint)},
|
||||
{typeof(long?[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Bigint)},
|
||||
{typeof(int[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Integer)},
|
||||
{typeof(int?[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Integer)},
|
||||
{typeof(short[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Smallint)},
|
||||
{typeof(short?[]), new(DbType.Object, NpgsqlDbType.Array | NpgsqlDbType.Smallint)}
|
||||
};
|
||||
|
||||
private readonly Dictionary<Type, string> typestrmap = new()
|
||||
{
|
||||
{typeof(byte), null! },
|
||||
{typeof(sbyte), null! },
|
||||
{typeof(short), "smallint" },
|
||||
{typeof(ushort), "smallint" },
|
||||
{typeof(int), "integer" },
|
||||
{typeof(uint), "integer" },
|
||||
{typeof(long), "bigint" },
|
||||
{typeof(ulong), "bigint" },
|
||||
{typeof(float), "real" },
|
||||
{typeof(double), "double precision" },
|
||||
{typeof(decimal), "money" },
|
||||
{typeof(bool), "boolean" },
|
||||
{typeof(string), "text" },
|
||||
{typeof(char), "character" },
|
||||
{typeof(Guid), "uuid" },
|
||||
{typeof(DateTime), "date" },
|
||||
{typeof(DateTimeOffset), "time with time zone" },
|
||||
{typeof(byte[]), "bytea" },
|
||||
{typeof(byte[][]), "bytea[]" },
|
||||
{typeof(byte?), null! },
|
||||
{typeof(sbyte?), null! },
|
||||
{typeof(short?), "smallint" },
|
||||
{typeof(ushort?), "smallint" },
|
||||
{typeof(int?), "integer" },
|
||||
{typeof(uint?), "integer" },
|
||||
{typeof(long?), "bigint" },
|
||||
{typeof(ulong?), "bigint" },
|
||||
{typeof(float?), "real" },
|
||||
{typeof(double?), "double precision" },
|
||||
{typeof(decimal?), "money" },
|
||||
{typeof(bool?), "boolean" },
|
||||
{typeof(char?), "character" },
|
||||
{typeof(Guid?), "uuid" },
|
||||
{typeof(DateTime?), "date" },
|
||||
{typeof(DateTimeOffset?), "time with time zone" },
|
||||
{typeof(string[]), "text[]" },
|
||||
{typeof(long[]), "bigint[]" },
|
||||
{typeof(long?[]), "bigint[]" },
|
||||
{typeof(int[]), "integer[]" },
|
||||
{typeof(int?[]), "integer[]" },
|
||||
{typeof(short[]), "smallint[]" },
|
||||
{typeof(short?[]), "smallint[]" }
|
||||
};
|
||||
}
|
15
Database/TableVersions.cs
Normal file
15
Database/TableVersions.cs
Normal file
@ -0,0 +1,15 @@
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class TableVersions : Table<TableVersions.blankrow>
|
||||
{
|
||||
internal TableVersions(Database db) : base(db)
|
||||
{
|
||||
ID = new TableColumn<short>("id", true);
|
||||
WithColumn(ID, new("ID"));
|
||||
}
|
||||
public class blankrow
|
||||
{
|
||||
|
||||
}
|
||||
public TableColumn<short> ID { get; }
|
||||
}
|
Loading…
Reference in New Issue
Block a user