|
@@ -1,6 +1,7 @@
|
|
|
using System.Collections;
|
|
|
using System.Data;
|
|
|
using System.Data.SQLite;
|
|
|
+using System.Diagnostics.CodeAnalysis;
|
|
|
using System.Linq.Expressions;
|
|
|
using System.Reflection;
|
|
|
using System.Runtime.Serialization.Formatters.Binary;
|
|
@@ -98,7 +99,7 @@ namespace InABox.Database.SQLite
|
|
|
|
|
|
public string URL { get; set; }
|
|
|
|
|
|
- public event LogEvent OnLog;
|
|
|
+ public event LogEvent? OnLog;
|
|
|
|
|
|
public Type[] Types { get; set; }
|
|
|
|
|
@@ -309,9 +310,9 @@ namespace InABox.Database.SQLite
|
|
|
result = command.ExecuteNonQuery();
|
|
|
}
|
|
|
}
|
|
|
- catch (Exception e)
|
|
|
+ catch (Exception)
|
|
|
{
|
|
|
- throw e;
|
|
|
+ throw;
|
|
|
}
|
|
|
|
|
|
return result;
|
|
@@ -566,7 +567,7 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
else if (property.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)))
|
|
|
{
|
|
|
- var subprop = property.PropertyType.GetProperty("ID");
|
|
|
+ var subprop = property.PropertyType.GetProperty("ID")!; // Not-null because IEntityLink has ID
|
|
|
var subname = ColumnName(prefixes.Concat(new[] { property, subprop }).ToArray());
|
|
|
var subtype = ColumnType(subprop.PropertyType);
|
|
|
fields[subname] = subtype;
|
|
@@ -594,7 +595,7 @@ namespace InABox.Database.SQLite
|
|
|
foreach (var property in properties)
|
|
|
if (property.PropertyType.GetInterfaces().Contains(typeof(IEntityLink)))
|
|
|
{
|
|
|
- var subprop = property.PropertyType.GetProperty("ID");
|
|
|
+ var subprop = property.PropertyType.GetProperty("ID")!; // Not-null because IEntityLink has ID
|
|
|
var subname = ColumnName(property, subprop);
|
|
|
var tablename = type.EntityName().Split('.').Last();
|
|
|
result.Add(string.Format("CREATE INDEX idx{0}{1} ON {0} ([{2}])", tablename, subname.Replace(".", ""), subname));
|
|
@@ -711,7 +712,7 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private Dictionary<String, object?> CheckDefaultColumns(IAutoEntityGenerator generator)
|
|
|
+ private Dictionary<string, object?> CheckDefaultColumns(IAutoEntityGenerator generator)
|
|
|
{
|
|
|
var viewfields = new Dictionary<string, string>();
|
|
|
LoadFields(generator.Definition, viewfields, null, new CustomProperty[] { });
|
|
@@ -734,7 +735,7 @@ namespace InABox.Database.SQLite
|
|
|
private void CreateTable(SQLiteWriteAccessor access, Type type, bool includeconstraints, CustomProperty[] customproperties)
|
|
|
{
|
|
|
var ddl = new List<string>();
|
|
|
- AutoEntity view = type.GetCustomAttribute<AutoEntity>();
|
|
|
+ var view = type.GetCustomAttribute<AutoEntity>();
|
|
|
if (view != null)
|
|
|
{
|
|
|
using (var command = access.CreateCommand())
|
|
@@ -760,9 +761,9 @@ namespace InABox.Database.SQLite
|
|
|
List<String> queries = new List<String>();
|
|
|
foreach (var table in union.Tables)
|
|
|
{
|
|
|
-
|
|
|
- var columns = Activator.CreateInstance(typeof(Columns<>).MakeGenericType(table.Entity)) as IColumns;
|
|
|
- Dictionary<String, object?> constants = CheckDefaultColumns(union);
|
|
|
+
|
|
|
+ var columns = Columns.Create(table.Entity);
|
|
|
+ var constants = CheckDefaultColumns(union);
|
|
|
|
|
|
var interfacefields = new Dictionary<string, string>();
|
|
|
LoadFields(union.Definition, interfacefields, null, new CustomProperty[] { });
|
|
@@ -786,7 +787,7 @@ namespace InABox.Database.SQLite
|
|
|
|
|
|
|
|
|
var selectFnc = typeof(SQLiteProvider).GetMethod("PrepareSelect").MakeGenericMethod(table.Entity);
|
|
|
- var query = selectFnc.Invoke(this, new object[]
|
|
|
+ var query = selectFnc.Invoke(this, new object?[]
|
|
|
{
|
|
|
new SQLiteCommand(),
|
|
|
'A',
|
|
@@ -928,7 +929,7 @@ namespace InABox.Database.SQLite
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
OnLog?.Invoke(LogType.Error, "Unable to Create Table: " + e.Message);
|
|
|
- throw e;
|
|
|
+ throw;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -965,7 +966,7 @@ namespace InABox.Database.SQLite
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
OnLog?.Invoke(LogType.Error, string.Format("RebuildTable({0}) [VIEW] failed: {1}\n{2}", table, e.Message, e.StackTrace));
|
|
|
- throw e;
|
|
|
+ throw;
|
|
|
}
|
|
|
}
|
|
|
else
|
|
@@ -1036,7 +1037,7 @@ namespace InABox.Database.SQLite
|
|
|
catch (Exception e)
|
|
|
{
|
|
|
OnLog?.Invoke(LogType.Error, string.Format("RebuildTable({0}) [TABLE] failed: {1}\n{2}", table, e.Message, e.StackTrace));
|
|
|
- throw e;
|
|
|
+ throw;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1057,7 +1058,7 @@ namespace InABox.Database.SQLite
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
- Type tType = null;
|
|
|
+ Type tType;
|
|
|
var cprop = customproperties.FirstOrDefault(x => string.Equals(x.Name, field));
|
|
|
if (cprop != null)
|
|
|
tType = cprop.PropertyType;
|
|
@@ -1130,17 +1131,17 @@ namespace InABox.Database.SQLite
|
|
|
// if (!db_views.ContainsValue(type_view))
|
|
|
// ExecuteSQL(access, type_view);
|
|
|
// }
|
|
|
-
|
|
|
+
|
|
|
#endregion
|
|
|
|
|
|
#region CRUD Operations
|
|
|
|
|
|
- private bool IsNull(object o)
|
|
|
+ private static bool IsNull([NotNullWhen(false)] object? o)
|
|
|
{
|
|
|
return o == null || o is DBNull;
|
|
|
}
|
|
|
|
|
|
- public object Decode(object o, Type type)
|
|
|
+ public object? Decode(object o, Type type)
|
|
|
{
|
|
|
if (IsNull(o))
|
|
|
return type == typeof(string) ? "" : type.GetDefault();
|
|
@@ -1149,54 +1150,56 @@ namespace InABox.Database.SQLite
|
|
|
{
|
|
|
if (!IsNull(o))
|
|
|
{
|
|
|
- var array = o as byte[];
|
|
|
- if (o is byte[])
|
|
|
- using (var ms = new MemoryStream((byte[])o))
|
|
|
+ if (o is byte[] array)
|
|
|
+ using (var ms = new MemoryStream(array))
|
|
|
{
|
|
|
var deser = new BinaryFormatter().Deserialize(ms);
|
|
|
return deser as string[];
|
|
|
}
|
|
|
|
|
|
- return new string[] { };
|
|
|
+ return Array.Empty<string>();
|
|
|
}
|
|
|
|
|
|
- return new string[] { };
|
|
|
+ return Array.Empty<string>();
|
|
|
}
|
|
|
|
|
|
if (type.GetInterfaces().Contains(typeof(IPackable)))
|
|
|
{
|
|
|
- var packable = Activator.CreateInstance(type) as IPackable;
|
|
|
+ var packable = (Activator.CreateInstance(type) as IPackable)!; // Not-null because of above check
|
|
|
if (!IsNull(o))
|
|
|
{
|
|
|
- var array = o as byte[];
|
|
|
- if (o is byte[])
|
|
|
- packable.Unpack(new FastBinaryReader((byte[])o));
|
|
|
+ if (o is byte[] array)
|
|
|
+ packable.Unpack(new FastBinaryReader(array));
|
|
|
}
|
|
|
|
|
|
return packable;
|
|
|
}
|
|
|
|
|
|
if (type == typeof(DateTime))
|
|
|
- return IsNull(o) || string.IsNullOrEmpty(o.ToString()) ? DateTime.MinValue : DateTime.Parse(o.ToString());
|
|
|
+ return IsNull(o) || string.IsNullOrEmpty(o.ToString()) ? DateTime.MinValue : DateTime.Parse(o.ToString() ?? "");
|
|
|
|
|
|
if (type == typeof(TimeSpan))
|
|
|
{
|
|
|
if (IsNull(o))
|
|
|
return TimeSpan.MinValue;
|
|
|
- if (double.TryParse(o.ToString(), out var hrs))
|
|
|
+ var oStr = o.ToString() ?? "";
|
|
|
+ if (double.TryParse(oStr, out var hrs))
|
|
|
return TimeSpan.FromHours(hrs);
|
|
|
- if (o.ToString().Contains(":"))
|
|
|
- return TimeSpan.Parse(o.ToString());
|
|
|
+ if (oStr.Contains(':'))
|
|
|
+ return TimeSpan.Parse(oStr);
|
|
|
}
|
|
|
|
|
|
if (type == typeof(Guid))
|
|
|
- return IsNull(o) ? Guid.Empty : Guid.Parse(o.ToString());
|
|
|
+ return IsNull(o) ? Guid.Empty : Guid.Parse(o.ToString() ?? "");
|
|
|
|
|
|
if (type == typeof(bool))
|
|
|
- return IsNull(o) ? false : o.ToString().Equals("1") || o.ToString().ToUpper().Equals("TRUE");
|
|
|
+ {
|
|
|
+ var oStr = o.ToString() ?? "";
|
|
|
+ return !IsNull(o) && (oStr.Equals("1") || oStr.ToUpper().Equals("TRUE"));
|
|
|
+ }
|
|
|
|
|
|
if (type.IsEnum)
|
|
|
- return Enum.Parse(type, o.ToString());
|
|
|
+ return Enum.Parse(type, o.ToString() ?? "");
|
|
|
|
|
|
if (IsNull(o))
|
|
|
return null;
|
|
@@ -1330,32 +1333,30 @@ namespace InABox.Database.SQLite
|
|
|
{ Operator.InQuery, "{0} IN ({1})" }
|
|
|
};
|
|
|
|
|
|
- private String EscapeValue(object value)
|
|
|
+ private static string EscapeValue(object? value)
|
|
|
{
|
|
|
if (IsNull(value))
|
|
|
return "NULL";
|
|
|
- if ((value is String) || (value is Enum) || (value is Guid))
|
|
|
- return String.Format("\'" + "{0}" + "\'", value.ToString().Replace("\'", "\'\'"));
|
|
|
- if (value is String[])
|
|
|
+ if ((value is string) || (value is Enum) || (value is Guid))
|
|
|
+ return string.Format("\'" + "{0}" + "\'", value.ToString()?.Replace("\'", "\'\'"));
|
|
|
+ if (value is string[])
|
|
|
return string.Format("hex({0})", BitConverter.ToString(Encoding.ASCII.GetBytes(value.ToString())).Replace("-", string.Empty));
|
|
|
- return value.ToString();
|
|
|
+ return value.ToString() ?? "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
- private String GetFilterConstant(FilterConstant constant)
|
|
|
+ private static string GetFilterConstant(FilterConstant constant)
|
|
|
{
|
|
|
- switch (constant)
|
|
|
+ return constant switch
|
|
|
{
|
|
|
- case FilterConstant.Now :
|
|
|
- return "datetime()";
|
|
|
- case FilterConstant.Today :
|
|
|
- return "strftime('%Y-%m-%d 00:00:00')";
|
|
|
- }
|
|
|
- throw new Exception($"FilterConstant.{constant} is not implemented!");
|
|
|
+ FilterConstant.Now => "datetime()",
|
|
|
+ FilterConstant.Today => "strftime('%Y-%m-%d 00:00:00')",
|
|
|
+ _ => throw new Exception($"FilterConstant.{constant} is not implemented!"),
|
|
|
+ };
|
|
|
}
|
|
|
-
|
|
|
- private string GetFilterClause<T>(SQLiteCommand command, char prefix, Filter<T> filter, List<Tuple<string, string, string, string>> tables,
|
|
|
+
|
|
|
+ private string GetFilterClause<T>(SQLiteCommand command, char prefix, Filter<T>? filter, List<Tuple<string, string, string, string>> tables,
|
|
|
Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
|
|
|
{
|
|
|
if (filter == null || filter.Expression == null)
|
|
@@ -1372,9 +1373,8 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- var prop = "";
|
|
|
- MemberExpression mexp = null;
|
|
|
- if (CoreUtils.TryFindMemberExpression(filter.Expression, out mexp))
|
|
|
+ string prop;
|
|
|
+ if (CoreUtils.TryFindMemberExpression(filter.Expression, out var mexp))
|
|
|
{
|
|
|
prop = CoreUtils.GetFullPropertyName(mexp, ".");
|
|
|
}
|
|
@@ -1394,16 +1394,14 @@ namespace InABox.Database.SQLite
|
|
|
{
|
|
|
// if, and only if the list contains Guids, we can safely bypass the
|
|
|
// 1000-parameter limit by using building the string ourselves
|
|
|
- if (filter.Value is Guid[])
|
|
|
+ if (filter.Value is Guid[] list)
|
|
|
{
|
|
|
- var list = filter.Value as Guid[];
|
|
|
result = string.Format("(" + operators[filter.Operator] + ")", prop, string.Format("\"{0}\"", string.Join("\",\"", list)));
|
|
|
}
|
|
|
- else if (filter.Value is IEnumerable)
|
|
|
+ else if (filter.Value is IEnumerable enumerable)
|
|
|
{
|
|
|
- var list = filter.Value as IEnumerable;
|
|
|
var paramlist = new List<object>();
|
|
|
- foreach (var item in list)
|
|
|
+ foreach (var item in enumerable)
|
|
|
{
|
|
|
var sParam = string.Format("@p{0}", command.Parameters.Count);
|
|
|
command.Parameters.AddWithValue(sParam, Encode(item, mexp.Type));
|
|
@@ -1447,8 +1445,8 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- if (filter.Value is FilterConstant)
|
|
|
- result = string.Format("(" + operators[filter.Operator] + ")", prop, GetFilterConstant((FilterConstant)filter.Value));
|
|
|
+ if (filter.Value is FilterConstant constant)
|
|
|
+ result = string.Format("(" + operators[filter.Operator] + ")", prop, GetFilterConstant(constant));
|
|
|
else
|
|
|
{
|
|
|
var value = Encode(filter.Value, mexp.Type);
|
|
@@ -1524,7 +1522,7 @@ namespace InABox.Database.SQLite
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- private string GetSortClause<T>(SQLiteCommand command, SortOrder<T> sort, char prefix, List<Tuple<string, string, string, string>> tables,
|
|
|
+ private string GetSortClause<T>(SQLiteCommand command, SortOrder<T>? sort, char prefix, List<Tuple<string, string, string, string>> tables,
|
|
|
Dictionary<string, string> fieldmap, List<string> columns, bool useparams) where T : Entity
|
|
|
{
|
|
|
if (sort == null)
|
|
@@ -1533,8 +1531,7 @@ namespace InABox.Database.SQLite
|
|
|
var result = "";
|
|
|
if (sort.Expression != null)
|
|
|
{
|
|
|
- MemberExpression mexp = null;
|
|
|
- if (CoreUtils.TryFindMemberExpression(sort.Expression, out mexp))
|
|
|
+ if (CoreUtils.TryFindMemberExpression(sort.Expression, out var mexp))
|
|
|
result = CoreUtils.GetFullPropertyName(mexp, ".");
|
|
|
else
|
|
|
result = sort.Expression.ToString();
|
|
@@ -1566,23 +1563,17 @@ namespace InABox.Database.SQLite
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- private string GetCalculation(AggregateAttribute attribute, string columnname)
|
|
|
+ private static string GetCalculation(AggregateAttribute attribute, string columnname)
|
|
|
{
|
|
|
- switch (attribute.Calculation)
|
|
|
+ return attribute.Calculation switch
|
|
|
{
|
|
|
- case AggregateCalculation.Sum:
|
|
|
- return "TOTAL";
|
|
|
- case AggregateCalculation.Count:
|
|
|
- return "COUNT";
|
|
|
- case AggregateCalculation.Maximum:
|
|
|
- return "MAX";
|
|
|
- case AggregateCalculation.Minimum:
|
|
|
- return "MIN";
|
|
|
- case AggregateCalculation.Average:
|
|
|
- return "AVERAGE";
|
|
|
- }
|
|
|
-
|
|
|
- throw new Exception(string.Format("{0}.{1} is not a valid aggregate", columnname, attribute.Calculator.GetType().Name));
|
|
|
+ AggregateCalculation.Sum => "TOTAL",
|
|
|
+ AggregateCalculation.Count => "COUNT",
|
|
|
+ AggregateCalculation.Maximum => "MAX",
|
|
|
+ AggregateCalculation.Minimum => "MIN",
|
|
|
+ AggregateCalculation.Average => "AVERAGE",
|
|
|
+ _ => throw new Exception(string.Format("{0}.{1} is not a valid aggregate", columnname, attribute.Calculator.GetType().Name)),
|
|
|
+ };
|
|
|
}
|
|
|
|
|
|
private string GetFunction(FormulaAttribute attribute, Dictionary<string, string> fieldmap, string columnname)
|
|
@@ -1739,11 +1730,10 @@ namespace InABox.Database.SQLite
|
|
|
var attr = prop.GetCustomAttributes().FirstOrDefault(x => x.GetType().Equals(typeof(AggregateAttribute)));
|
|
|
// LogStop("GetCustomAttributes(Aggregate)");
|
|
|
|
|
|
- if (attr != null)
|
|
|
+ if (attr is AggregateAttribute agg)
|
|
|
{
|
|
|
- var agg = attr as AggregateAttribute;
|
|
|
-
|
|
|
- bool internalaggregate = agg.Calculator.GetType().GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition()== typeof(ICoreAggregate<,>));
|
|
|
+ bool internalaggregate = agg.Calculator.GetType().GetInterfaces()
|
|
|
+ .Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICoreAggregate<,>));
|
|
|
|
|
|
if (internalaggregate)
|
|
|
{
|
|
@@ -1775,14 +1765,7 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // LogStart();
|
|
|
- var subcoltype = typeof(Columns<>).MakeGenericType(linkedtype);
|
|
|
- // LogStop("Columns<>.MakeGnericType");
|
|
|
-
|
|
|
- // LogStart();
|
|
|
- var subcols = Activator.CreateInstance(subcoltype) as IColumns;
|
|
|
- // LogStop("Columns<>.CreateInstance");
|
|
|
-
|
|
|
+ var subcols = Columns.Create(linkedtype);
|
|
|
|
|
|
foreach (var key in agg.Links.Keys)
|
|
|
subcols.Add(key);
|
|
@@ -1810,7 +1793,7 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
|
|
|
var linkedtable = string.Format("({0})",
|
|
|
- preparemethod.Invoke(this, new object[] { command, newprefix, filter, subcols, null, scols, null, int.MaxValue, false, useparams }));
|
|
|
+ preparemethod.Invoke(this, new object?[] { command, newprefix, filter, subcols, null, scols, null, int.MaxValue, false, useparams }));
|
|
|
|
|
|
var alias = tables.Count + 1;
|
|
|
|
|
@@ -1853,9 +1836,8 @@ namespace InABox.Database.SQLite
|
|
|
attr = prop.GetCustomAttributes().FirstOrDefault(x => x.GetType().Equals(typeof(FormulaAttribute)));
|
|
|
// LogStop("GetAttribute(Formula)");
|
|
|
|
|
|
- if (attr != null)
|
|
|
+ if (attr is FormulaAttribute fnc)
|
|
|
{
|
|
|
- var fnc = attr as FormulaAttribute;
|
|
|
var functionmap = new Dictionary<string, string>();
|
|
|
|
|
|
// LogStart();
|
|
@@ -1885,10 +1867,8 @@ namespace InABox.Database.SQLite
|
|
|
attr = prop.GetCustomAttributes().FirstOrDefault(x => x.GetType().Equals(typeof(ConditionAttribute)));
|
|
|
// LogStop("GetAttribute(Condition)");
|
|
|
|
|
|
- if (attr != null)
|
|
|
+ if (attr is ConditionAttribute cnd)
|
|
|
{
|
|
|
- var cnd = attr as ConditionAttribute;
|
|
|
-
|
|
|
var cndmap = new Dictionary<string, string>();
|
|
|
// LogStart();
|
|
|
CheckColumn(columns, cnd.Left);
|
|
@@ -1983,13 +1963,7 @@ namespace InABox.Database.SQLite
|
|
|
if (!siblings.Contains("Deleted"))
|
|
|
siblings.Insert(1, "Deleted");
|
|
|
|
|
|
- // LogStart();
|
|
|
- var subcoltype = typeof(Columns<>).MakeGenericType(linkedtype);
|
|
|
- // LogStop("Columns<>.MakeGenericType");
|
|
|
-
|
|
|
- // LogStart();
|
|
|
- var subcols = Activator.CreateInstance(subcoltype) as IColumns;
|
|
|
- // LogStop("Columns<>.CreateInstance");
|
|
|
+ var subcols = Columns.Create(linkedtype);
|
|
|
|
|
|
foreach (var sibling in siblings)
|
|
|
subcols.Add(sibling);
|
|
@@ -2130,7 +2104,7 @@ namespace InABox.Database.SQLite
|
|
|
condition = GetFilterClause(command, prefix, filter, tables, fieldmap, fields, useparams);
|
|
|
sortorder = GetSortClause(command, sort, prefix, tables, fieldmap, fields, useparams);
|
|
|
|
|
|
- SortedDictionary<String,String> combined = new SortedDictionary<String, String>();
|
|
|
+ var combined = new SortedDictionary<string, string>();
|
|
|
|
|
|
fields.Clear();
|
|
|
foreach (var column in cols.Items)
|
|
@@ -2214,7 +2188,7 @@ namespace InABox.Database.SQLite
|
|
|
continue;
|
|
|
|
|
|
var sParam = string.Format("@p{0}", iParam++);
|
|
|
- object value = null;
|
|
|
+ object? value = null;
|
|
|
try
|
|
|
{
|
|
|
value = Encode(insert[key], insert[key]?.GetType());
|
|
@@ -2449,7 +2423,7 @@ namespace InABox.Database.SQLite
|
|
|
ReadAndDecodeValue(result, reader, row, i);
|
|
|
}
|
|
|
}
|
|
|
- catch (Exception e)
|
|
|
+ catch (Exception)
|
|
|
{
|
|
|
row.Values.Add(result.Columns[i].DataType.GetDefault());
|
|
|
}
|
|
@@ -2537,7 +2511,7 @@ namespace InABox.Database.SQLite
|
|
|
entity.SetObserving(false);
|
|
|
for (var i = 0; i < reader.FieldCount; i++)
|
|
|
{
|
|
|
- object value = null;
|
|
|
+ object value;
|
|
|
if (cols.Items[i].Expression.Type == typeof(long) && !reader.IsDBNull(i))
|
|
|
value = reader.GetInt64(i);
|
|
|
else
|
|
@@ -2943,6 +2917,12 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
|
|
|
var entityType = CoreUtils.Entities.FirstOrDefault(x => x.Name == deletion.HeadTable);
|
|
|
+ if(entityType is null)
|
|
|
+ {
|
|
|
+ Logger.Send(LogType.Error, "", $"Entity {deletion.HeadTable} does not exist; Purge cancelled");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
var deletionTypes = GetDeletionTypes(entityType);
|
|
|
|
|
|
var purgeMethod = typeof(SQLiteProvider).GetMethod(nameof(PurgeEntityType), BindingFlags.NonPublic | BindingFlags.Instance)!;
|
|
@@ -2963,6 +2943,11 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
|
|
|
var entityType = CoreUtils.Entities.FirstOrDefault(x => x.Name == deletion.HeadTable);
|
|
|
+ if (entityType is null)
|
|
|
+ {
|
|
|
+ Logger.Send(LogType.Error, "", $"Entity {deletion.HeadTable} does not exist; Recovery cancelled");
|
|
|
+ return;
|
|
|
+ }
|
|
|
var deletionTypes = GetDeletionTypes(entityType);
|
|
|
|
|
|
var recoveryMethod = typeof(SQLiteProvider).GetMethod(nameof(RecoverEntityType), BindingFlags.NonPublic | BindingFlags.Instance)!;
|
|
@@ -2981,6 +2966,6 @@ namespace InABox.Database.SQLite
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
-
|
|
|
+
|
|
|
}
|
|
|
}
|