Browse Source

Some more work on this

Kenric Nugteren 1 year ago
parent
commit
d35b9eb029
3 changed files with 75 additions and 144 deletions
  1. 6 0
      InABox.Core/Client/Client.cs
  2. 61 144
      InABox.Core/DataModel/DataModel.cs
  3. 8 0
      InABox.Core/Filter.cs

+ 6 - 0
InABox.Core/Client/Client.cs

@@ -107,6 +107,12 @@ namespace InABox.Clients
             }
             }
         }
         }
 
 
+        public static CoreTable Query<TEntity>(QueryDef<TEntity> query)
+            where TEntity : Entity, IRemotable, IPersistent, new()
+        {
+            return new Client<TEntity>().Query(query.Filter, query.Columns, query.SortOrder);
+        }
+
         public static CoreTable Query<TEntity>(Filter<TEntity>? filter = null, Columns<TEntity>? columns = null, SortOrder<TEntity>? orderby = null)
         public static CoreTable Query<TEntity>(Filter<TEntity>? filter = null, Columns<TEntity>? columns = null, SortOrder<TEntity>? orderby = null)
             where TEntity : Entity, IRemotable, IPersistent, new()
             where TEntity : Entity, IRemotable, IPersistent, new()
         {
         {

+ 61 - 144
InABox.Core/DataModel/DataModel.cs

@@ -230,7 +230,7 @@ namespace InABox.Core
             AddTable(new Filter<User>(x => x.ID).IsEqualTo(ClientFactory.UserGuid), null, true);
             AddTable(new Filter<User>(x => x.ID).IsEqualTo(ClientFactory.UserGuid), null, true);
         }
         }
 
 
-        public IEnumerable<KeyValuePair<string, DataModelTable>> ModelTables => _tables;
+        public IEnumerable<KeyValuePair<string, IDataModelTable>> ModelTables => _tables;
 
 
         public abstract string Name { get; }
         public abstract string Name { get; }
 
 
@@ -409,19 +409,29 @@ namespace InABox.Core
             }
             }
         }
         }
 
 
-        public class DataModelLoadTable<T> : IDataModelTable
-            where T : Entity, IRemotable, IPersistent, new()
+        private interface IDataModelLoadTable : IDataModelTable
         {
         {
-            private CoreTable? _data = null;
+            public IFilter? GetFilter();
+
+            public IQueryDef GetQueryDef();
+
+            public void LoadData(CoreTable data);
+        }
 
 
+        public class DataModelLoadTable<T> : IDataModelTable, IDataModelLoadTable
+            where T : Entity, IRemotable, IPersistent, new()
+        {
             public string Name { get; set; }
             public string Name { get; set; }
 
 
             public Type? Type => typeof(T);
             public Type? Type => typeof(T);
 
 
             public DataModel Model { get; set; }
             public DataModel Model { get; set; }
 
 
-            public CoreTable Data => throw new NotImplementedException();
+            public CoreTable Data { get; private set; }
 
 
+            /// <summary>
+            /// Set to <see langword="true"/> if this table should be included in lists of default required tables. Thus, this is not used for the actual loading of data; use <see cref="IsRequired"/> for that.
+            /// </summary>
             public bool IsDefault { get; set; }
             public bool IsDefault { get; set; }
             public bool IsRequired { get; set; }
             public bool IsRequired { get; set; }
 
 
@@ -429,7 +439,8 @@ namespace InABox.Core
 
 
             public Columns<T> Columns { get; set; }
             public Columns<T> Columns { get; set; }
 
 
-            public IEnumerable<IDataModelTable> ChildTables => Model._relationships.Where(x => x.ParentTable == Name).Select(x => Model._tables[x.ChildTable]);
+            public IEnumerable<IDataModelTable> ChildTables =>
+                Model._relationships.Where(x => x.ParentTable == Name).Select(x => Model._tables[x.ChildTable]);
 
 
             public DataModelLoadTable(DataModel model, string name, Filter<T> filter, Columns<T> columns)
             public DataModelLoadTable(DataModel model, string name, Filter<T> filter, Columns<T> columns)
             {
             {
@@ -469,96 +480,50 @@ namespace InABox.Core
                 }
                 }
 
 
                 var childName = TableName<TChild>(alias);
                 var childName = TableName<TChild>(alias);
-                var single = relations.Where(x => x.Name == childName).SingleOrDefault();
-                if(single is null)
-                {
-                    throw new AmbiguousTableException<TChild>();
-                }
+                var single = relations.Where(x => x.Name == childName).SingleOrDefault()
+                    ?? throw new AmbiguousTableException<TChild>();
                 return single;
                 return single;
             }
             }
 
 
             public void Load()
             public void Load()
             {
             {
-                throw new NotImplementedException();
+                Data = Client.Query(GetQueryDef());
             }
             }
-        }
-
-        #region New Load Methods
-
-        private Filter<TChild> GetSubquery<TParent, TChild>(IDataModelRelationship relation, Dictionary<string, IQueryDef> requiredQueries)
-            where TParent : Entity, IRemotable, IPersistent, new()
-            where TChild : Entity, IRemotable, IPersistent, new()
-        {
-            var parentFilter = GetTableFilter<TParent>(relation.ParentTable, requiredQueries);
-            var subQuery = new SubQuery<TParent>(parentFilter, new Column<TParent>(relation.ParentColumnAsPropertyName()));
-
-            var filter = new Filter<TChild>();
-            filter.Expression = CoreUtils.CreateMemberExpression(typeof(TChild), relation.ChildColumnAsPropertyName());
-            filter.Operator = Operator.InQuery;
-            filter.Value = subQuery;
 
 
-            return filter;
-        }
-
-        private Filter<TType>? GetTableFilter<TType>(string tableName, Dictionary<string, IQueryDef> requiredQueries)
-            where TType : Entity, IRemotable, IPersistent, new()
-        {
-            var newFilter = _tables[tableName].Filter as Filter<TType>;
-
-            IQueryDef? query = null;
-            requiredQueries?.TryGetValue(tableName, out query);
-            if (query?.Filter is Filter<TType> filter)
+            public Filter<T>? GetFilter()
             {
             {
-                if (newFilter != null)
-                    newFilter.And(filter);
-                else
-                    newFilter = filter;
-            }
-
-            var relation = _relationships.Where(x => x.ChildTable == tableName).FirstOrDefault();
-            if (relation != null)
-            {
-                var table = _tables[relation.ParentTable];
-
-                if(table.Type != null)
+                var relation = Model._relationships.Where(x => x.ChildTable == Name).FirstOrDefault();
+                if(relation != null && Model._tables[relation.ParentTable] is IDataModelLoadTable loadTable && loadTable.Type is Type parentType)
                 {
                 {
-                    var subFilter = (typeof(DataModel).GetMethod(nameof(GetSubquery), BindingFlags.NonPublic | BindingFlags.Instance)
-                    .MakeGenericMethod(_tables[relation.ParentTable].Type, typeof(TType))
-                    .Invoke(this, new object?[] { relation, requiredQueries }) as Filter<TType>)!;
+                    var subFilter = new Filter<T>(relation.ChildColumnAsPropertyName());
+                    subFilter.Operator = Operator.InQuery;
+                    subFilter.Value = SubQuery.Create(parentType,
+                        loadTable.GetFilter(),
+                        Column.Create(parentType, relation.ParentColumnAsPropertyName()));
 
 
-                    if (newFilter != null)
-                        newFilter.And(subFilter);
-                    else
-                        newFilter = subFilter;
+                    return Filters<T>.Combine(Filter, subFilter);
                 }
                 }
+                return Filter;
             }
             }
 
 
-            return newFilter;
-        }
+            IFilter? IDataModelLoadTable.GetFilter() => GetFilter();
 
 
-        private IQueryDef LoadModelTable<TType>(string tableName, Dictionary<string, IQueryDef> requiredQueries)
-            where TType : Entity, IRemotable, IPersistent, new()
-        {
-            var newFilter = GetTableFilter<TType>(tableName, requiredQueries);
-
-            var newColumns = _tables[tableName].Columns as Columns<TType>;
-
-            var newSort = LookupFactory.DefineSort<TType>();
-
-            IQueryDef? query = null;
-            requiredQueries?.TryGetValue(tableName, out query);
+            public QueryDef<T> GetQueryDef()
+            {
+                return new QueryDef<T>(GetFilter(), Columns, LookupFactory.DefineSort<T>());
+            }
 
 
-            if (query == null) return new QueryDef<TType>(newFilter, newColumns, newSort);
+            IQueryDef IDataModelLoadTable.GetQueryDef() => GetQueryDef();
 
 
-            if (query.Columns != null) newColumns = query.Columns as Columns<TType>;
-            return new QueryDef<TType>(
-                newFilter,
-                newColumns,
-                query.SortOrder as SortOrder<TType>
-            );
+            public void LoadData(CoreTable data)
+            {
+                Data = data;
+            }
         }
         }
 
 
-        public virtual void LoadModel(IEnumerable<string>? requiredTables, Dictionary<string, IQueryDef>? requiredQueries = null)
+        #region New Load Methods
+
+        public virtual void LoadModel(IEnumerable<string>? requiredTables)
         {
         {
             var requiredTablesList = requiredTables != null ? requiredTables.ToList() : new List<string>();
             var requiredTablesList = requiredTables != null ? requiredTables.ToList() : new List<string>();
             CheckRequiredTables(requiredTablesList);
             CheckRequiredTables(requiredTablesList);
@@ -568,36 +533,33 @@ namespace InABox.Core
             if (!args.Cancel) BeforeLoad(requiredTablesList);
             if (!args.Cancel) BeforeLoad(requiredTablesList);
 
 
             var queries = new Dictionary<string, IQueryDef>();
             var queries = new Dictionary<string, IQueryDef>();
-            var genericMethod = typeof(DataModel).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance)
-                .Where(x => x.Name == nameof(LoadModelTable) && x.IsGenericMethod)
-                .FirstOrDefault()!;
-            foreach (var table in _tables)
-                if (table.Value.ShouldLoad)
-                    if (requiredTables == null || requiredTablesList.Contains(table.Key))
-                        queries[table.Key] = (genericMethod.MakeGenericMethod(table.Value.Type).Invoke(this, new object?[]
-                        {
-                            table.Key,
-                            requiredQueries
-                        }) as IQueryDef)!;
+            foreach (var (key, table) in _tables)
+            {
+                if(requiredTables is null || requiredTablesList.Contains(key))
+                {
+                    if(table is IDataModelLoadTable loadTable)
+                    {
+                        queries[key] = loadTable.GetQueryDef();
+                    }
+                    else
+                    {
+                        table.Load();
+                    }
+                }
+            }
 
 
             var results = Client.QueryMultiple(queries);
             var results = Client.QueryMultiple(queries);
-            foreach (var result in results)
-                if (_tables.TryGetValue(result.Key, out var table))
-                    table.Table = result.Value;
+            foreach (var (key, data) in results)
+                if (_tables.TryGetValue(key, out var table) && table is IDataModelLoadTable loadTable)
+                    loadTable.LoadData(data);
                 else
                 else
-                    Logger.Send(LogType.Error, "",
-                        string.Format("QueryMultiple returned table with key {0}, which is not in the data model!", result.Key));
+                    Logger.Send(LogType.Error, "", $"QueryMultiple returned table with key {key}, which is not in the data model!");
 
 
             args = new CancelEventArgs();
             args = new CancelEventArgs();
             OnAfterLoad?.Invoke(args);
             OnAfterLoad?.Invoke(args);
             if (!args.Cancel) AfterLoad(requiredTablesList);
             if (!args.Cancel) AfterLoad(requiredTablesList);
         }
         }
 
 
-        public void LoadModel(IEnumerable<string>? requiredTables, params IDataModelQueryDef[] requiredQueries)
-        {
-            LoadModel(requiredTables, requiredQueries.ToDictionary(x => x.TableName, x => x as IQueryDef));
-        }
-
         public void LoadModel()
         public void LoadModel()
         {
         {
             LoadModel(DefaultTableNames);
             LoadModel(DefaultTableNames);
@@ -819,51 +781,6 @@ namespace InABox.Core
         public bool RemoveTable<TType>(string? alias = null) => RemoveTable(typeof(TType), alias);
         public bool RemoveTable<TType>(string? alias = null) => RemoveTable(typeof(TType), alias);
 
 
         #endregion
         #endregion
-
-        #region Cache of Link Values based on relationships
-
-        // Type = Parent, String = ParentColumn, List=Values
-        //private Dictionary<Type, Dictionary<String, List<object>>> _ids = new Dictionary<Type, Dictionary<String, List<object>>>();
-
-        // private void SetupIds<TType>(String columnname)
-        //{
-        //    if (!_ids.ContainsKey(typeof(TParent)))
-        //        _ids[typeof(TParent)] = new Dictionary<string, List<object>>();
-        //    _ids[typeof(TParent)][relationship.ParentColumn] = new List<object>();
-        //}
-
-        //private void ClearIDs<TType>()
-        //{
-        //    if (_ids.ContainsKey(typeof(TType)))
-        //    {
-        //        var cols = _ids[typeof(TType)];
-        //        foreach (var col in cols.Keys)
-        //            cols[col].Clear();
-        //    }
-        //}
-
-        //private void UpdateIDs<TType>()
-        //{
-        //    if (_ids.ContainsKey(typeof(TType)))
-        //    {
-        //        var cols = _ids[typeof(TType)];
-        //        foreach (var col in cols.Keys)
-        //            cols[col].AddRange(GetTable<TType>().ExtractValues<object>(col, true));
-        //    }
-        //}
-
-        //protected object[] GetIDs<TType>(String column)
-        //{
-        //    if (_ids.ContainsKey(typeof(TType)))
-        //    {
-        //        var cols = _ids[typeof(TType)];
-        //        if (cols.ContainsKey(column))
-        //            return cols[column].ToArray();
-        //    }
-        //    return new object[] { };
-        //}
-
-        #endregion
     }
     }
 
 
     public abstract class DataModel<T> : DataModel, IDataModel<T>
     public abstract class DataModel<T> : DataModel, IDataModel<T>

+ 8 - 0
InABox.Core/Filter.cs

@@ -21,6 +21,14 @@ namespace InABox.Core
         IColumn GetColumn();
         IColumn GetColumn();
     }
     }
 
 
+    public static class SubQuery
+    {
+        public static ISubQuery Create(Type T, IFilter? filter, IColumn column)
+        {
+            return (Activator.CreateInstance(typeof(SubQuery<>).MakeGenericType(T), filter, column) as ISubQuery)!;
+        }
+    }
+
     public class SubQuery<T> : ISubQuery
     public class SubQuery<T> : ISubQuery
     {
     {
         public SubQuery()
         public SubQuery()