ForeignKeys & CommandHandler
This commit is contained in:
parent
aa1e57f6e3
commit
e9ec3638c5
91
Database/CommandHandler.cs
Normal file
91
Database/CommandHandler.cs
Normal file
@ -0,0 +1,91 @@
|
||||
using Npgsql;
|
||||
using ServerDatabase.Utils;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class CommandHandler
|
||||
{
|
||||
private IBetterTable _betterTable;
|
||||
|
||||
internal CommandHandler(IBetterTable betterTable)
|
||||
{
|
||||
this._betterTable = betterTable;
|
||||
}
|
||||
|
||||
private List<Parameter> Parameters = new();
|
||||
private List<Parameter> Values = new();
|
||||
|
||||
private Order? Order = null;
|
||||
|
||||
public CommandHandler WithFilter(Parameter p)
|
||||
{
|
||||
Parameters.Add(p);
|
||||
return this;
|
||||
}
|
||||
public CommandHandler WithValue(Parameter p)
|
||||
{
|
||||
Values.Add(p);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandHandler WithFilter<T>(TableColumn<T> column, T value, string sign = "=") where T : notnull
|
||||
{
|
||||
return WithFilter(column.CreateParameter(value, sign));
|
||||
}
|
||||
|
||||
public CommandHandler WithValue<T>(TableColumn<T> column, T value) where T : notnull
|
||||
{
|
||||
return WithValue(column.CreateParameter(value));
|
||||
}
|
||||
|
||||
public CommandHandler AscendBy<T>(TableColumn<T> column) where T : notnull
|
||||
{
|
||||
Order = column.GetAssendingOrder();
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandHandler DescendBy<T>(TableColumn<T> column) where T : notnull
|
||||
{
|
||||
Order = column.GetDecendingOrder();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public T Read<T>(TableColumn<T> column) where T : notnull
|
||||
{
|
||||
return _betterTable.DatabaseHandler.Read<T>($"SELECT {column.Name} FROM {_betterTable.Name} WHERE", Order, Parameters.ToArray());
|
||||
}
|
||||
|
||||
public void Insert()
|
||||
{
|
||||
_betterTable.Insert(Values.ToArray());
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_betterTable.DatabaseHandler.DB) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.IP) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.Uname) || string.IsNullOrEmpty(_betterTable.DatabaseHandler.PW)) throw new Exception("Database connection not fully defined");
|
||||
using NpgsqlConnection con = new(_betterTable.DatabaseHandler.ConectionString);
|
||||
con.Open();
|
||||
using NpgsqlCommand cmd = new();
|
||||
cmd.Connection = con;
|
||||
string values = "";
|
||||
foreach (Parameter param in Values)
|
||||
{
|
||||
values += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName}, ";
|
||||
cmd.Parameters.Add(param.PGParameter);
|
||||
}
|
||||
values = values.Remove(values.Length - 2, 2);
|
||||
|
||||
string fils = "";
|
||||
foreach (Parameter param in Parameters)
|
||||
{
|
||||
fils += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName} AND";
|
||||
cmd.Parameters.Add(param.PGParameter);
|
||||
}
|
||||
fils = fils.Remove(fils.Length - 4, 4);
|
||||
cmd.CommandText = $"UPDATE {_betterTable.Name} SET {values} WHERE {fils};";
|
||||
cmd.Prepare();
|
||||
cmd.ExecuteNonQuery();
|
||||
con.Close();
|
||||
}
|
||||
}
|
@ -1,8 +1,4 @@
|
||||
using Npgsql;
|
||||
using NpgsqlTypes;
|
||||
using System.Data;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using ServerDatabase.Utils;
|
||||
|
||||
namespace ServerDatabase;
|
||||
@ -17,7 +13,7 @@ public sealed class Database
|
||||
}
|
||||
}
|
||||
|
||||
public List<ITable> Tables { get; } = new()
|
||||
public List<IBetterTable> Tables { get; } = new()
|
||||
{
|
||||
};
|
||||
|
||||
@ -38,7 +34,7 @@ public sealed class Database
|
||||
|
||||
public void RegisterTables()
|
||||
{
|
||||
foreach (ITable Table in Tables)
|
||||
foreach (IBetterTable Table in Tables)
|
||||
{
|
||||
foreach (ITableColumn Column in Table.Colums)
|
||||
{
|
||||
@ -49,7 +45,7 @@ public sealed class Database
|
||||
}
|
||||
}
|
||||
VersionsTable.UpdateTable();
|
||||
foreach (ITable Table in Tables)
|
||||
foreach (IBetterTable Table in Tables)
|
||||
{
|
||||
Table.UpdateTable();
|
||||
}
|
||||
|
31
Database/ForeignKey.cs
Normal file
31
Database/ForeignKey.cs
Normal file
@ -0,0 +1,31 @@
|
||||
using ServerDatabase.Utils;
|
||||
using ServerDatabase.Utils.Enums;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class ForeignKey : IForeignKey
|
||||
{
|
||||
public ConstraintAction OnUpdate { get; init; } = ConstraintAction.None;
|
||||
public ConstraintAction OnDelete { get; init; } = ConstraintAction.None;
|
||||
public KeyMatchType MatchType { get; init; } = KeyMatchType.Simple;
|
||||
|
||||
public required ITable Table { get; init; }
|
||||
public required ITableColumn Column { get; init; }
|
||||
|
||||
private bool d = false;
|
||||
|
||||
public bool Deferrable { get; init; } = false;
|
||||
|
||||
public bool Deferred
|
||||
{
|
||||
get
|
||||
{
|
||||
return d & Deferrable;
|
||||
}
|
||||
init
|
||||
{
|
||||
d = value;
|
||||
}
|
||||
}
|
||||
public bool Validated { get; init; } = false;
|
||||
}
|
8
Database/IBetterTable.cs
Normal file
8
Database/IBetterTable.cs
Normal file
@ -0,0 +1,8 @@
|
||||
using ServerDatabase.Utils;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public interface IBetterTable : ITable
|
||||
{
|
||||
public Database DatabaseHandler { get; set; }
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
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);
|
||||
}
|
@ -10,8 +10,8 @@
|
||||
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
|
||||
<PackageTags>Postgresql;sql</PackageTags>
|
||||
<Title>Server Database</Title>
|
||||
<Version>2.8.9</Version>
|
||||
<LangVersion>10</LangVersion>
|
||||
<Version>2.9.9</Version>
|
||||
<LangVersion>11</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
@ -22,8 +22,7 @@
|
||||
<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" />
|
||||
<PackageReference Include="ServerDatabase.Utils" Version="1.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,13 +1,13 @@
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
using Npgsql;
|
||||
using ServerDatabase.Utils;
|
||||
using ServerDatabase.Utils.Enums;
|
||||
|
||||
namespace ServerDatabase;
|
||||
|
||||
public class Table<TRow> : ITable where TRow : class, new()
|
||||
public class Table<TRow> : IBetterTable where TRow : class, new()
|
||||
{
|
||||
public Table(string Name, Database DB)
|
||||
{
|
||||
@ -22,6 +22,11 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
DatabaseHandler = DB;
|
||||
}
|
||||
|
||||
public CommandHandler CreateCommand()
|
||||
{
|
||||
return new CommandHandler(this);
|
||||
}
|
||||
|
||||
public Table<TRow> WithColumn(ITableColumn Column, string name)
|
||||
{
|
||||
Colums_.Add(Column);
|
||||
@ -35,7 +40,6 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
Colums_.Add(Column);
|
||||
}
|
||||
|
||||
|
||||
public IReadOnlyList<ITableColumn> GetMissingColumns(out IReadOnlyList<ITableColumn> UpdatedColumns, out string[] ExtraColumns)
|
||||
{
|
||||
List<ITableColumn> coll = new(Colums_);
|
||||
@ -222,25 +226,94 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
con.Open();
|
||||
using NpgsqlCommand cmd = new();
|
||||
cmd.Connection = con;
|
||||
string command = $"CREATE TABLE public.{Name}(";
|
||||
string key = "";
|
||||
string command = $"CREATE TABLE IF NOT EXISTS public.{Name}(";
|
||||
List<string> Keys = new();
|
||||
|
||||
List<Tuple<ITableColumn, IForeignKey>> FKeys = new();
|
||||
foreach (ITableColumn column in Colums_)
|
||||
{
|
||||
command += $"{column.Name} {column.GetDatabaseTypeStr()}";
|
||||
if (column.IsPrimaryKey) key = $"PRIMARY KEY ({column.Name})";
|
||||
if (column.IsPrimaryKey) Keys.Add(column.Name);
|
||||
command += " NOT NULL, ";
|
||||
if (column.ForeignKeys.Length > 0)
|
||||
{
|
||||
foreach (IForeignKey Fkey in column.ForeignKeys)
|
||||
{
|
||||
FKeys.Add(new(column, Fkey));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (key == "") command = command.Remove(command.Length - 2, 2) + ");";
|
||||
command += $"{key});";
|
||||
|
||||
if (Keys.Count > 0)
|
||||
{
|
||||
string key = $"CONSTRAINT {Name}_pkey PRIMARY KEY (";
|
||||
foreach (var Key in Keys)
|
||||
{
|
||||
key += Key + ", ";
|
||||
}
|
||||
|
||||
key = key.Remove(key.Length - 2, 2);
|
||||
key += "), ";
|
||||
command += key;
|
||||
}
|
||||
|
||||
if (FKeys.Count > 0)
|
||||
{
|
||||
foreach (Tuple<ITableColumn, IForeignKey> K in FKeys)
|
||||
{
|
||||
string key = $"CONSTRAINT {Name}_{K.Item1.Name}_{K.Item2.Table.Name}_{K.Item2.Column.Name}_fkey FOREIGN KEY ({K.Item1.Name}) REFERENCES public.{K.Item2.Table.Name} ({K.Item2.Column.Name}) MATCH ";
|
||||
if (K.Item2.MatchType == KeyMatchType.Full) key += "FULL ON UPDATE ";
|
||||
else key += "SIMPLE ON UPDATE ";
|
||||
switch (K.Item2.OnUpdate)
|
||||
{
|
||||
case ConstraintAction.None:
|
||||
key += "NO ACTION ON DELETE ";
|
||||
break;
|
||||
case ConstraintAction.Cascade:
|
||||
key += "CASCADE ON DELETE ";
|
||||
break;
|
||||
case ConstraintAction.Restrict:
|
||||
key += "RESTRICT ON DELETE ";
|
||||
break;
|
||||
case ConstraintAction.SetDefault:
|
||||
key += "SET DEFAULT ON DELETE ";
|
||||
break;
|
||||
}
|
||||
switch (K.Item2.OnDelete)
|
||||
{
|
||||
case ConstraintAction.None:
|
||||
key += "NO ACTION ";
|
||||
break;
|
||||
case ConstraintAction.Cascade:
|
||||
key += "CASCADE ";
|
||||
break;
|
||||
case ConstraintAction.Restrict:
|
||||
key += "RESTRICT ";
|
||||
break;
|
||||
case ConstraintAction.SetDefault:
|
||||
key += "SET DEFAULT ";
|
||||
break;
|
||||
}
|
||||
|
||||
if (K.Item2.Deferrable) key += "DEFERRABLE ";
|
||||
if (K.Item2.Deferred) key += "INITIALLY DEFERRED ";
|
||||
if (!K.Item2.Validated) key += "NOT VALID ";
|
||||
key = key.Remove(key.Length - 1, 1) + ", ";
|
||||
command += key;
|
||||
}
|
||||
}
|
||||
|
||||
command = command.Remove(command.Length - 2, 2);
|
||||
|
||||
command += ");";
|
||||
cmd.CommandText = command;
|
||||
cmd.Prepare();
|
||||
cmd.ExecuteNonQuery();
|
||||
con.Close();
|
||||
DatabaseHandler.ExecuteNonQuery($"ALTER TABLE IF EXISTS " +
|
||||
$"public.{Name} OWNER to \"{DatabaseHandler.Uname}\";");
|
||||
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
|
||||
public bool TryRead<T>(TableColumn<T> column, Order order, [NotNullWhen(true)]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);
|
||||
@ -361,9 +434,9 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
return r;
|
||||
}
|
||||
|
||||
public bool TryReadRows(out TRow[] rows, params Parameter[] Parameters) => TryReadRows(null!, out rows, Parameters);
|
||||
public bool TryReadRows([NotNullWhen(true)]out TRow[]? rows, params Parameter[] Parameters) => TryReadRows(null!, out rows, Parameters);
|
||||
|
||||
public bool TryReadRows(Order order, out TRow[] rows, params Parameter[] Parameters)
|
||||
public bool TryReadRows(Order order, [NotNullWhen(true)]out TRow[]? rows, 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);
|
||||
@ -389,9 +462,9 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
List<TRow> Rows = new();
|
||||
while (reader.Read())
|
||||
{
|
||||
TRow Row = new();
|
||||
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))
|
||||
@ -405,15 +478,15 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
}
|
||||
pi.SetValue(Row, val, null);
|
||||
}
|
||||
Rows.Add(Row);
|
||||
}
|
||||
Rows.Add(Row);
|
||||
}
|
||||
|
||||
rows = Rows.ToArray();
|
||||
return Rows.Any();
|
||||
}
|
||||
|
||||
public bool TryRead<T>(TableColumn<T> column, [NotNullWhen(true)][MaybeNullWhen(false)]out T result, params Parameter[] Parameters) where T : notnull
|
||||
public bool TryRead<T>(TableColumn<T> column, [NotNullWhen(true)]out T? result, params Parameter[] Parameters) where T : notnull
|
||||
{
|
||||
return TryRead(column, null!, out result, Parameters);
|
||||
}
|
||||
@ -425,23 +498,12 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
|
||||
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)
|
||||
CommandHandler command = CreateCommand().WithFilter(condiction_column, condiction_value, Sign);
|
||||
foreach (var Parameter in Parameters)
|
||||
{
|
||||
vals += $"{param.PGParameter.ParameterName} {param.Sign} @{param.PGParameter.ParameterName}, ";
|
||||
cmd.Parameters.Add(param.PGParameter);
|
||||
command.WithValue(Parameter);
|
||||
}
|
||||
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();
|
||||
command.Update();
|
||||
}
|
||||
|
||||
public TRow ReadRow(params Parameter[] Parameters) => ReadRow(null, Parameters);
|
||||
@ -491,9 +553,53 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
return Row;
|
||||
}
|
||||
|
||||
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, params Parameter[] Parameters) where TColumn : notnull => ReadColumn(column, uint.MaxValue, null, Parameters);
|
||||
|
||||
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, uint NumRows, params Parameter[] Parameters) where TColumn : notnull => ReadColumn(column, NumRows, null, Parameters);
|
||||
|
||||
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, Order? Order, params Parameter[] Parameters) where TColumn : notnull => ReadColumn(column, uint.MaxValue, Order, Parameters);
|
||||
|
||||
public TColumn[] ReadColumn<TColumn>(TableColumn<TColumn> column, uint NumRows, Order? order, params Parameter[] Parameters) where TColumn : 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);
|
||||
string command = $"SELECT {column.Name} 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 (command.EndsWith("WHERE")) command = command.Remove(command.Length - 6, 6);
|
||||
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<TColumn> Rows = new();
|
||||
for (int j = 0; j < NumRows; j++)
|
||||
{
|
||||
if (!reader.Read()) break;
|
||||
Rows.Add((TColumn)reader.GetValue(0));
|
||||
}
|
||||
|
||||
return Rows.ToArray();
|
||||
}
|
||||
|
||||
public TRow[] ReadRows(params Parameter[] Parameters) => ReadRows(uint.MaxValue, null, Parameters);
|
||||
|
||||
public TRow[] ReadRows(uint NumRows, params Parameter[] Parameters) => ReadRows(NumRows, null, Parameters);
|
||||
|
||||
public TRow[] ReadRows(uint NumRows, Order order, params Parameter[] Parameters)
|
||||
public TRow[] ReadRows(Order? Order, params Parameter[] Parameters) => ReadRows(uint.MaxValue, Order, 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);
|
||||
@ -510,6 +616,7 @@ public class Table<TRow> : ITable where TRow : class, new()
|
||||
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 (command.EndsWith("WHERE")) command = command.Remove(command.Length - 6, 6);
|
||||
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"; }
|
||||
|
@ -14,6 +14,8 @@ public class TableColumn<Ttype> : ITableColumn where Ttype : notnull
|
||||
this.IsPrimaryKey = IsPrimaryKey;
|
||||
}
|
||||
|
||||
public IForeignKey[] ForeignKeys { get; init; } = Array.Empty<IForeignKey>();
|
||||
|
||||
public long ColumnVersion { get; set; } = 0;
|
||||
public Order GetDecendingOrder() => new Order() { Assending = false, Type = Name };
|
||||
public Order GetAssendingOrder() => new Order() { Assending = true, Type = Name };
|
||||
|
Loading…
Reference in New Issue
Block a user