Преглед на файлове

Extracted LoadForeignProperties into Client

Kenric Nugteren преди 10 месеца
родител
ревизия
1437ba0d1c
променени са 3 файла, в които са добавени 120 реда и са изтрити 94 реда
  1. 118 0
      InABox.Core/Client/Client.cs
  2. 1 8
      inabox.wpf/DynamicGrid/DynamicGrid.cs
  3. 1 86
      inabox.wpf/DynamicGrid/IDynamicMemoryEntityGrid.cs

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

@@ -35,6 +35,24 @@ namespace InABox.Clients
             where T: BaseObject, new() 
             => Results[typeof(T).Name].ToObjects<T>();
 
+        /// <summary>
+        /// Like <see cref="Get{T}"/>, but calls <see cref="CoreTable.ToArray{T}"/> on the table.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns></returns>
+        public T[] GetArray<T>()
+            where T: BaseObject, new() 
+            => Results[typeof(T).Name].ToArray<T>();
+
+        /// <summary>
+        /// Like <see cref="Get{T}"/>, but calls <see cref="CoreTable.ToList{T}"/> on the table.
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns></returns>
+        public List<T> GetList<T>()
+            where T: BaseObject, new() 
+            => Results[typeof(T).Name].ToList<T>();
+
         public CoreTable Get(string name) => Results[name];
 
         public CoreTable GetOrDefault(string name) => Results.GetValueOrDefault(name);
@@ -659,4 +677,104 @@ namespace InABox.Clients
             }
         }
     }
+
+    public static class ClientExtensions
+    {
+        /// <summary>
+        /// Load the properties of any <see cref="EntityLink{T}"/>s on this <typeparamref name="T"/> where the <see cref="IEntityLink.ID"/> is not <see cref="Guid.Empty"/>.
+        /// This allows us to populate columns of transient objects, as long as they are linked by the ID. What this actually then does is query each
+        /// linked table with the required columns.
+        /// </summary>
+        /// <param name="columns"></param>
+        public static void LoadForeignProperties<T>(this IEnumerable<T> items, Columns<T> columns)
+            where T : BaseObject, new()
+        {
+            // Lists of properties that we need, arranged by the entity link property which is their parent.
+            // LinkIDProperty : (Type, Properties: [(columnName, property)], Objects)
+            var newData = new Dictionary<IProperty, Tuple<Type, List<Tuple<string, IProperty>>, HashSet<T>>>();
+
+            foreach (var column in columns)
+            {
+                var property = DatabaseSchema.Property(typeof(T), column.Property);
+                if (property?.GetOuterParent(x => x.IsEntityLink) is IProperty linkProperty)
+                {
+                    var remaining = column.Property[(linkProperty.Name.Length + 1)..];
+                    if (remaining.Equals(nameof(IEntityLink.ID)))
+                    {
+                        // This guy isn't foreign, so we don't pull him.
+                        continue;
+                    }
+
+                    var idProperty = DatabaseSchema.Property(typeof(T), linkProperty.Name + "." + nameof(IEntityLink.ID))!;
+
+                    var linkType = linkProperty.PropertyType.GetInterfaceDefinition(typeof(IEntityLink<>))!.GenericTypeArguments[0];
+                    if (!newData.TryGetValue(idProperty, out var data))
+                    {
+                        data = new Tuple<Type, List<Tuple<string, IProperty>>, HashSet<T>>(
+                            linkType,
+                            new List<Tuple<string, IProperty>>(),
+                            new HashSet<T>());
+                        newData.Add(idProperty, data);
+                    }
+
+                    var any = false;
+                    foreach (var item in items)
+                    {
+                        if (!item.LoadedColumns.Contains(column.Property))
+                        {
+                            var linkID = (Guid)idProperty.Getter()(item);
+                            if (linkID != Guid.Empty)
+                            {
+                                any = true;
+                                data.Item3.Add(item);
+                            }
+                        }
+                    }
+                    if (any)
+                    {
+                        data.Item2.Add(new Tuple<string, IProperty>(remaining, property));
+                    }
+                }
+            }
+
+            var queryDefs = new List<IKeyedQueryDef>();
+            foreach (var (prop, data) in newData)
+            {
+                if (data.Item2.Count != 0)
+                {
+                    var ids = data.Item3.Select(prop.Getter()).Cast<Guid>().ToArray();
+                    queryDefs.Add(new KeyedQueryDef(prop.Name, data.Item1,
+                        Filter.Create<Entity>(data.Item1, x => x.ID).InList(ids),
+                        Columns.None(data.Item1)
+                            .Add(data.Item2.Select(x => x.Item1))
+                            .Add<Entity>(x => x.ID)));
+                }
+            }
+            var results = Client.QueryMultiple(queryDefs);
+            foreach(var (prop, data) in newData)
+            {
+                var table = results.GetOrDefault(prop.Name);
+                if(table is null)
+                {
+                    continue;
+                }
+                foreach (var entity in data.Item3)
+                {
+                    var linkID = (Guid)prop.Getter()(entity);
+                    var row = table.Rows.FirstOrDefault(x => x.Get<Entity, Guid>(x => x.ID) == linkID);
+                    if (row != null)
+                    {
+                        foreach (var (name, property) in data.Item2)
+                        {
+                            if (!entity.LoadedColumns.Contains(property.Name))
+                            {
+                                property.Setter()(entity, row[name]);
+                                entity.LoadedColumns.Add(property.Name);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
 }

+ 1 - 8
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -1336,14 +1336,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
 
     public virtual T[] LoadItems(CoreRow[] rows)
     {
-        var result = new List<T>();
-        foreach (var row in rows)
-        {
-            var index = Data.Rows.IndexOf(row);
-            result.Add(LoadItem(row));
-        }
-
-        return result.ToArray();
+        return rows.ToArray(LoadItem);
     }
 
     public abstract T LoadItem(CoreRow row);

+ 1 - 86
inabox.wpf/DynamicGrid/IDynamicMemoryEntityGrid.cs

@@ -53,92 +53,7 @@ public static class DynamicMemoryEntityGridExtensions
     public static void LoadForeignProperties<T>(this IDynamicMemoryEntityGrid<T> grid, Columns<T> columns)
         where T : Entity, IRemotable, IPersistent, new()
     {
-        // Lists of properties that we need, arranged by the entity link property which is their parent.
-        // LinkIDProperty : (Type, Properties: [(columnName, property)], Objects)
-        var newData = new Dictionary<IProperty, Tuple<Type, List<Tuple<string, IProperty>>, HashSet<T>>>();
-
-        foreach (var column in columns)
-        {
-            var property = DatabaseSchema.Property(typeof(T), column.Property);
-            if (property?.GetOuterParent(x => x.IsEntityLink) is IProperty linkProperty)
-            {
-                var remaining = column.Property[(linkProperty.Name.Length + 1)..];
-                if (remaining.Equals(nameof(IEntityLink.ID)))
-                {
-                    // This guy isn't foreign, so we don't pull him.
-                    continue;
-                }
-
-                var idProperty = DatabaseSchema.Property(typeof(T), linkProperty.Name + "." + nameof(IEntityLink.ID))!;
-
-                var linkType = linkProperty.PropertyType.GetInterfaceDefinition(typeof(IEntityLink<>))!.GenericTypeArguments[0];
-                if (!newData.TryGetValue(idProperty, out var data))
-                {
-                    data = new Tuple<Type, List<Tuple<string, IProperty>>, HashSet<T>>(
-                        linkType,
-                        new List<Tuple<string, IProperty>>(),
-                        new HashSet<T>());
-                    newData.Add(idProperty, data);
-                }
-
-                var any = false;
-                foreach (var item in grid.Items)
-                {
-                    if (!item.LoadedColumns.Contains(column.Property))
-                    {
-                        var linkID = (Guid)idProperty.Getter()(item);
-                        if (linkID != Guid.Empty)
-                        {
-                            any = true;
-                            data.Item3.Add(item);
-                        }
-                    }
-                }
-                if (any)
-                {
-                    data.Item2.Add(new(remaining, property));
-                }
-            }
-        }
-
-        var queryDefs = new List<IKeyedQueryDef>();
-        foreach (var (prop, data) in newData)
-        {
-            if (data.Item2.Count != 0)
-            {
-                var ids = data.Item3.Select(prop.Getter()).Cast<Guid>().ToArray();
-                queryDefs.Add(new KeyedQueryDef(prop.Name, data.Item1,
-                    Filter.Create<Entity>(data.Item1, x => x.ID).InList(ids),
-                    Columns.None(data.Item1)
-                        .Add(data.Item2.Select(x => x.Item1))
-                        .Add<Entity>(x => x.ID)));
-            }
-        }
-        var results = Client.QueryMultiple(queryDefs);
-        foreach(var (prop, data) in newData)
-        {
-            var table = results.GetOrDefault(prop.Name);
-            if(table is null)
-            {
-                continue;
-            }
-            foreach (var entity in data.Item3)
-            {
-                var linkID = (Guid)prop.Getter()(entity);
-                var row = table.Rows.FirstOrDefault(x => x.Get<Entity, Guid>(x => x.ID) == linkID);
-                if (row is not null)
-                {
-                    foreach (var (name, property) in data.Item2)
-                    {
-                        if (!entity.LoadedColumns.Contains(property.Name))
-                        {
-                            property.Setter()(entity, row[name]);
-                            entity.LoadedColumns.Add(property.Name);
-                        }
-                    }
-                }
-            }
-        }
+        grid.Items.LoadForeignProperties(columns);
     }
 
     public static void RequireColumns<T>(this IDynamicMemoryEntityGrid<T> grid, Columns<T> columns)