Prechádzať zdrojové kódy

Made it so OneToMany and ManyToMany grids don't save AutoEntities. Made it so Client.Delete can take IEnumerable

Kenric Nugteren 1 rok pred
rodič
commit
7f886d3f91

+ 1 - 1
InABox.Client.Local/LocalClient.cs

@@ -202,7 +202,7 @@ namespace InABox.Clients
             store.Delete(entity, auditnote);
         }
 
-        protected override void DoDelete(IList<TEntity> entities, string auditnote)
+        protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)
         {
             var store = DbFactory.FindStore<TEntity>(ClientFactory.UserGuid, ClientFactory.UserID, ClientFactory.Platform, ClientFactory.Version);
             store.Delete(entities, auditnote);

+ 1 - 1
InABox.Client.RPC/RPCClient.cs

@@ -206,7 +206,7 @@ namespace InABox.Rpc
             DoDelete(new TEntity[] { entity }, auditnote);
         }
 
-        protected override void DoDelete(IList<TEntity> entities, string auditnote)
+        protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)
         {
             var parameters = new RpcDeleteParameters()
             {

+ 10 - 10
InABox.Core/Client/BaseClient.cs

@@ -184,10 +184,10 @@ namespace InABox.Clients
             Task.Run(() =>
             {
                 Exception? err = null;
+                var items = entities.AsArray();
                 try
                 {
-                    var items = entities.ToArray();
-                    DoSave(entities, auditnote);
+                    DoSave(items, auditnote);
                 }
                 catch (Exception e)
                 {
@@ -195,7 +195,7 @@ namespace InABox.Clients
                 }
                 finally
                 {
-                    callback.Invoke(entities, err);
+                    callback.Invoke(items, err);
                 }
             });
         }
@@ -213,7 +213,7 @@ namespace InABox.Clients
             DoDelete((TEntity)entity, auditnote);
         }
 
-        public void Delete(IList<object> entities, string auditnote)
+        public void Delete(IEnumerable<object> entities, string auditnote)
         {
             var items = entities.Select(x => (TEntity)x).ToList();
             DoDelete(items, auditnote);
@@ -224,7 +224,7 @@ namespace InABox.Clients
             DoDelete(entity, auditnote);
         }
 
-        public void Delete(IList<TEntity> entities, string auditnote)
+        public void Delete(IEnumerable<TEntity> entities, string auditnote)
         {
             DoDelete(entities, auditnote);
         }
@@ -250,15 +250,15 @@ namespace InABox.Clients
             );
         }
 
-        public void Delete(IList<TEntity> entities, string auditnote, Action<IList<TEntity>, Exception?> callback)
+        public void Delete(IEnumerable<TEntity> entities, string auditnote, Action<IList<TEntity>, Exception?> callback)
         {
             Task.Run(() =>
             {
                 Exception? err = null;
-                var items = entities;
+                var items = entities.ToArray();
                 try
                 {
-                    DoDelete(entities, auditnote);
+                    DoDelete(items, auditnote);
                 }
                 catch (Exception e)
                 {
@@ -266,14 +266,14 @@ namespace InABox.Clients
                 }
                 finally
                 {
-                    callback.Invoke(entities, err);
+                    callback.Invoke(items, err);
                 }
             });
         }
 
         protected abstract void DoDelete(TEntity entity, string auditnote);
 
-        protected abstract void DoDelete(IList<TEntity> entities, string auditnote);
+        protected abstract void DoDelete(IEnumerable<TEntity> entities, string auditnote);
 
         #endregion
 

+ 44 - 12
InABox.Core/Client/Client.cs

@@ -66,10 +66,38 @@ namespace InABox.Clients
             }
         }
 
+        private static IClient<TEntity> CheckClient<TEntity>() where TEntity : Entity, IRemotable, IPersistent, new()
+        {
+            return ClientFactory.CreateClient<TEntity>();
+        }
+
         public static CoreTable Query<TEntity>(Filter<TEntity>? filter = null, Columns<TEntity>? columns = null, SortOrder<TEntity>? orderby = null)
             where TEntity : Entity, IRemotable, IPersistent, new()
         {
-            return new Client<TEntity>().Query(filter, columns, orderby);
+            return CheckClient<TEntity>().Query(filter, columns, orderby);
+        }
+
+        public static void Save<TEntity>(TEntity entity, string auditNote)
+            where TEntity : Entity, IRemotable, IPersistent, new()
+        {
+            CheckClient<TEntity>().Save(entity, auditNote);
+        }
+        public static void Save<TEntity>(IEnumerable<TEntity> entities, string auditNote)
+            where TEntity : Entity, IRemotable, IPersistent, new()
+        {
+            CheckClient<TEntity>().Save(entities, auditNote);
+        }
+
+        public static void Delete<TEntity>(TEntity entity, string auditNote)
+            where TEntity : Entity, IRemotable, IPersistent, new()
+        {
+            CheckClient<TEntity>().Delete(entity, auditNote);
+        }
+
+        public static void Delete<TEntity>(IEnumerable<TEntity> entities, string auditNote)
+            where TEntity : Entity, IRemotable, IPersistent, new()
+        {
+            CheckClient<TEntity>().Delete(entities, auditNote);
         }
 
         public static void QueryMultiple(
@@ -438,9 +466,10 @@ namespace InABox.Clients
             {
                 using var timer = new Profiler<TEntity>(false);
                 CheckSupported();
-                if (entities.Any())
-                    _client.Save(entities, auditnote);
-                timer.Log(entities.Count());
+                var items = entities.AsArray();
+                if (items.Any())
+                    _client.Save(items, auditnote);
+                timer.Log(items.Length);
             }
             catch (RequestException e)
             {
@@ -455,8 +484,9 @@ namespace InABox.Clients
             {
                 var timer = new Profiler<TEntity>(false);
                 CheckSupported();
-                if (entities.Any())
-                    _client.Save(entities, auditnote, (i, e) =>
+                var items = entities.AsArray();
+                if (items.Any())
+                    _client.Save(items, auditnote, (i, e) =>
                     {
                         timer.Dispose(i.Count());
                         callback?.Invoke(i, e);
@@ -506,14 +536,15 @@ namespace InABox.Clients
             }
         }
 
-        public void Delete(IList<TEntity> entities, string auditnote)
+        public void Delete(IEnumerable<TEntity> entities, string auditnote)
         {
             try
             {
                 using var timer = new Profiler<TEntity>(false);
                 CheckSupported();
-                _client.Delete(entities, auditnote);
-                timer.Log(entities.Count());
+                var items = entities.AsArray();
+                _client.Delete(items, auditnote);
+                timer.Log(items.Length);
             }
             catch (RequestException e)
             {
@@ -522,15 +553,16 @@ namespace InABox.Clients
             }
         }
 
-        public void Delete(IList<TEntity> entities, string auditnote, Action<IList<TEntity>, Exception?> callback)
+        public void Delete(IEnumerable<TEntity> entities, string auditnote, Action<IList<TEntity>, Exception?> callback)
         {
             try
             {
                 var timer = new Profiler<TEntity>(false);
                 CheckSupported();
-                _client.Delete(entities, auditnote, (i, e) =>
+                var items = entities.AsArray();
+                _client.Delete(items, auditnote, (i, e) =>
                 {
-                    timer.Dispose(entities.Count());
+                    timer.Dispose(i.Count);
                     callback?.Invoke(i, e);
                 });
             }

+ 3 - 3
InABox.Core/Client/IClient.cs

@@ -18,7 +18,7 @@ namespace InABox.Clients
         void Save(object entity, string auditnote);
         void Save(IEnumerable<object> entities, string auditnote);
         void Delete(object entity, string auditnote);
-        void Delete(IList<object> entities, string auditnote);
+        void Delete(IEnumerable<object> entities, string auditnote);
         Dictionary<string, CoreTable> QueryMultiple(Dictionary<string, IQueryDef> queries);
         void QueryMultiple(Action<Dictionary<string, CoreTable>?, Exception?> callback, Dictionary<string, IQueryDef> queries);
 
@@ -65,9 +65,9 @@ namespace InABox.Clients
         void Save(IEnumerable<TEntity> entity, string auditnote, Action<IEnumerable<TEntity>, Exception?> callback);
 
         void Delete(TEntity entity, string auditnote);
-        void Delete(IList<TEntity> entities, string auditnote);
+        void Delete(IEnumerable<TEntity> entities, string auditnote);
         void Delete(TEntity entity, string auditnote, Action<TEntity, Exception?> callback);
-        void Delete(IList<TEntity> entity, string auditnote, Action<IList<TEntity>, Exception?> callback);
+        void Delete(IEnumerable<TEntity> entity, string auditnote, Action<IList<TEntity>, Exception?> callback);
         
     }
 

+ 15 - 0
InABox.Core/CoreUtils.cs

@@ -334,6 +334,8 @@ namespace InABox.Core
             return null;
         }
 
+        public static bool HasAttribute<T>(this Type type) where T : Attribute => type.GetCustomAttribute<T>() != null;
+
         #endregion
 
         public static bool TryGetEntity(string entityname, [NotNullWhen(true)] out Type? type)
@@ -2717,6 +2719,19 @@ namespace InABox.Core
             return enumerable.ToList<T>();
         }
 
+        /// <summary>
+        /// Returns <paramref name="enumerable"/> as an array;
+        /// if it is already an array, it is directly returned, instead of copying.
+        /// </summary>
+        public static T[] AsArray<T>(this IEnumerable<T> enumerable)
+        {
+            if (enumerable is T[] arr)
+            {
+                return arr;
+            }
+            return enumerable.ToArray<T>();
+        }
+
         public static IEnumerable<T> AnyOr<T>(this IEnumerable<T> enumerable, IEnumerable<T> or)
         {
             var any = false;

+ 2 - 2
inabox.client.ipc/IPCClient.cs

@@ -130,9 +130,9 @@ namespace InABox.IPC
             }
         }
 
-        protected override void DoDelete(IList<TEntity> entities, string auditnote)
+        protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)
         {
-            var items = entities.ToArray();
+            var items = entities.AsArray();
             var request = new MultiDeleteRequest<TEntity>(items, auditnote);
             PrepareRequest(request);
 

+ 2 - 2
inabox.client.rest/InABox.Client.Rest/RestClient.cs

@@ -493,9 +493,9 @@ namespace InABox.Clients
             }
         }
 
-        protected override void DoDelete(IList<TEntity> entities, string auditnote)
+        protected override void DoDelete(IEnumerable<TEntity> entities, string auditnote)
         {
-            var items = entities.ToArray();
+            var items = entities.AsArray();
             var request = new MultiDeleteRequest<TEntity>(items, auditnote);
 
             PrepareRequest(request);

+ 4 - 5
inabox.wpf/DigitalForms/DigitalFormUtils.cs

@@ -173,7 +173,7 @@ namespace InABox.DynamicGrid
                 if (string.IsNullOrWhiteSpace(cell.Content) && style.Foreground == Color.Empty) continue;
 
                 DFLayoutControl? control;
-                String content = cell.Content?.Trim() ?? "";
+                var content = cell.Content?.Trim() ?? "";
 
                 var headermatch = HeaderRegex.Match(content);
                 var variablematch = VariableRegex.Match(content);
@@ -185,7 +185,7 @@ namespace InABox.DynamicGrid
                     var header = new DFLayoutHeader()
                     {
                         Header = text.Value, 
-                        Collapsed = collapsed.Success ? String.Equals(collapsed.Value.ToUpper(),"COLLAPSED") : false,
+                        Collapsed = collapsed.Success && String.Equals(collapsed.Value.ToUpper(),"COLLAPSED"),
                         Style = CreateStyle(style)
                     };
                     
@@ -221,7 +221,7 @@ namespace InABox.DynamicGrid
                 {
                     control = new DFLayoutLabel
                     {
-                        Caption = cell.Content,
+                        Caption = content,
                         Style = CreateStyle(style)
                     };
                 }
@@ -490,8 +490,7 @@ namespace InABox.DynamicGrid
             float startotal = 0F;
             for (int iStar = 0; iStar < values.Count; iStar++)
             {
-                float fstartotal = 0F;
-                if (values[iStar].Contains("*"))
+                if (values[iStar].Contains('*'))
                 {
                     if (!float.TryParse(values[iStar].Replace("*", ""), out float value))
                         value += 1;

+ 16 - 8
inabox.wpf/DynamicGrid/DynamicManyToManyGrid.cs

@@ -27,6 +27,8 @@ namespace InABox.DynamicGrid
         private TManyToMany[] MasterList = { };
         protected PropertyInfo otherproperty;
 
+        protected IEntityLink GetOtherLink(TManyToMany item) => (otherproperty.GetValue(item) as IEntityLink)!;
+
         protected PropertyInfo thisproperty;
         protected List<TManyToMany> WorkingList = new();
 
@@ -46,6 +48,8 @@ namespace InABox.DynamicGrid
             }
         }
 
+        private static bool IsAutoEntity => typeof(TManyToMany).HasAttribute<AutoEntity>();
+
         public DynamicManyToManyGrid()
         {
             MultiSelect = true;
@@ -149,6 +153,10 @@ namespace InABox.DynamicGrid
 
         public void AfterSave(object item)
         {
+            if (IsAutoEntity)
+            {
+                return;
+            }
             // First remove any deleted files
             foreach (var map in MasterList)
                 if (!WorkingList.Contains(map))
@@ -156,7 +164,7 @@ namespace InABox.DynamicGrid
 
             foreach (var map in WorkingList)
             {
-                var prop = (IEntityLink)thisproperty.GetValue(map);
+                var prop = GetOtherLink(map);
                 if (prop.ID != Item.ID)
                     prop.ID = Item.ID;
             }
@@ -170,10 +178,10 @@ namespace InABox.DynamicGrid
             return new Size(400, 400);
         }
 
-        private Type OtherType() =>
+        private static Type OtherType() =>
             CoreUtils.GetManyToManyOtherType(typeof(TManyToMany), typeof(TThis));
 
-        private string GetTag()
+        private static string GetTag()
         {
             return typeof(TManyToMany).Name + "." + typeof(TThis).Name;
         }
@@ -251,7 +259,7 @@ namespace InABox.DynamicGrid
             var result = new List<Guid>();
             foreach (var item in WorkingList)
             {
-                var prop = (IEntityLink)otherproperty.GetValue(item);
+                var prop = GetOtherLink(item);
                 result.Add(prop.ID);
             }
 
@@ -261,7 +269,7 @@ namespace InABox.DynamicGrid
 
         protected virtual object GetFilter()
         {
-            var result = LookupFactory.DefineFilter(OtherType(), typeof(TThis), new[] { (TThis)Item }) as IFilter;
+            var result = LookupFactory.DefineFilter(OtherType(), typeof(TThis), new[] { (TThis)Item });
 
             var filtertype = typeof(Filter<>).MakeGenericType(OtherType());
 
@@ -293,7 +301,7 @@ namespace InABox.DynamicGrid
                 var filter = GetFilter();
 
                 var dlgtype = typeof(MultiSelectDialog<>).MakeGenericType(OtherType());
-                var dlg = Activator.CreateInstance(dlgtype, filter, null, true) as IMultiSelectDialog;
+                var dlg = (Activator.CreateInstance(dlgtype, filter, null, true) as IMultiSelectDialog)!;
                 if (dlg.ShowDialog())
                 {
                     var guids = CurrentGuids();
@@ -304,7 +312,7 @@ namespace InABox.DynamicGrid
                         if (!guids.Contains(entity.ID))
                         {
                             var newitem = CreateItem();
-                            var prop = (IEntityLink)otherproperty.GetValue(newitem);
+                            var prop = GetOtherLink(newitem);
                             prop.ID = entity.ID;
                             prop.Synchronise(entity);
                             SaveItem(newitem);
@@ -325,7 +333,7 @@ namespace InABox.DynamicGrid
             var result = new TManyToMany();
             if (Item != null)
             {
-                var prop = (IEntityLink)thisproperty.GetValue(result);
+                var prop = GetOtherLink(result);
                 prop.ID = Item.ID;
                 prop.Synchronise(Item);
             }

+ 14 - 4
inabox.wpf/DynamicGrid/DynamicOneToManyGrid.cs

@@ -25,7 +25,7 @@ namespace InABox.DynamicGrid
     public class DynamicOneToManyGrid<TOne, TMany> : DynamicGrid<TMany>, IDynamicEditorPage, IDynamicOneToManyGrid<TOne, TMany>
         where TOne : Entity, new() where TMany : Entity, IPersistent, IRemotable, new()
     {
-        private TMany[] MasterList = { };
+        private TMany[] MasterList = Array.Empty<TMany>();
         private readonly PropertyInfo property;
 
         public PageType PageType => PageType.Other;
@@ -90,6 +90,8 @@ namespace InABox.DynamicGrid
             }
         }
 
+        private static bool IsAutoEntity => typeof(TMany).HasAttribute<AutoEntity>();
+
         protected Filters<TMany> Criteria { get; } = new Filters<TMany>();
 
         public TOne Item { get; protected set; }
@@ -152,11 +154,19 @@ namespace InABox.DynamicGrid
 
         protected virtual void OnDeleteItem(TMany item)
         {
+            if (IsAutoEntity)
+            {
+                return;
+            }
             new Client<TMany>().Delete(item, typeof(TMany).Name + " Deleted by User");
         }
 
         public void AfterSave(object item)
         {
+            if (IsAutoEntity)
+            {
+                return;
+            }
             // First remove any deleted files
             foreach (var map in MasterList)
                 if (!Items.Contains(map))
@@ -207,7 +217,7 @@ namespace InABox.DynamicGrid
             Items.AddRange(items);
             Refresh(false, true);
         }
-        private string GetTag()
+        private static string GetTag()
         {
             return typeof(TOne).Name + "." + typeof(TMany).Name;
         }
@@ -283,7 +293,7 @@ namespace InABox.DynamicGrid
         protected override TMany CreateItem()
         {
             var result = new TMany();
-            var prop = (IEntityLink)property.GetValue(result);
+            var prop = (property.GetValue(result) as IEntityLink)!;
             prop.ID = Item.ID;
             prop.Synchronise(Item);
             return result;
@@ -307,7 +317,7 @@ namespace InABox.DynamicGrid
             if (!Items.Contains(item))
                 Items.Add(item);
 
-            if (item is ISequenceable) Items = Items.AsQueryable().OrderBy(x => (x as ISequenceable).Sequence).ToList();
+            if (item is ISequenceable) Items = Items.AsQueryable().OrderBy(x => (x as ISequenceable)!.Sequence).ToList();
             //var sort = LookupFactory.DefineSort<TMany>();
             //if (sort != null)
             //    Items = Items.AsQueryable().SortBy(sort.Expression).ToList();

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

@@ -189,7 +189,7 @@ namespace InABox.DynamicGrid
             else if (window?.DialogResult == false)
                 return new T[] { new T() };
 
-            return new T[] { };
+            return Array.Empty<T>();
         }
 
         private void Grid_DoubleClick(object sender, HandledEventArgs args)