Parcourir la source

Added DatabaseSchema.LocalProperties, and improved Merging functionality in the unlikely event of entity links on EnclosedEntities.

Kenric Nugteren il y a 9 mois
Parent
commit
5e0683e299

+ 10 - 0
InABox.Core/DatabaseSchema/DatabaseSchema.cs

@@ -338,6 +338,16 @@ namespace InABox.Core
         public static IEnumerable<IProperty> RootProperties(Type type)
         public static IEnumerable<IProperty> RootProperties(Type type)
             => PropertiesInternal(type).Where(x => x.Parent is null);
             => PropertiesInternal(type).Where(x => x.Parent is null);
 
 
+        /// <summary>
+        /// Return all properties that are defined locally on <paramref name="type"/>, following sub-objects but not entity links; does not retrieve calculated fields. (On entity links, the ID property is retrieved.)
+        /// </summary>
+        /// <param name="type"></param>
+        /// <returns></returns>
+        public static IEnumerable<IProperty> LocalProperties(Type type)
+            => PropertiesInternal(type).Where(
+                x => (!x.HasParentEntityLink() || (x.Parent?.HasParentEntityLink() != true && x.Name.EndsWith(".ID")))
+                    && !x.IsCalculated);
+
         /// <summary>
         /// <summary>
         /// Return the standard property list for <paramref name="type"/>; this includes nested properties.
         /// Return the standard property list for <paramref name="type"/>; this includes nested properties.
         /// </summary>
         /// </summary>

+ 6 - 0
InABox.Core/Entity.cs

@@ -51,6 +51,12 @@ namespace InABox.Core
     {
     {
     }
     }
 
 
+    /// <summary>
+    ///     Indicate that an <see cref="Entity"/> is able to be merged together.
+    /// </summary>
+    /// <remarks>
+    ///     It is recommended that an <see cref="Entity"/> that implements this should provide a <see cref="object.ToString"/> implementation.
+    /// </remarks>
     public interface IMergeable
     public interface IMergeable
     {
     {
     }
     }

+ 23 - 26
inabox.wpf/DynamicGrid/DynamicDataGrid.cs

@@ -12,6 +12,7 @@ using System.Windows.Controls;
 using InABox.Clients;
 using InABox.Clients;
 using InABox.Configuration;
 using InABox.Configuration;
 using InABox.Core;
 using InABox.Core;
+using InABox.Wpf;
 using InABox.WPF;
 using InABox.WPF;
 using Expression = System.Linq.Expressions.Expression;
 using Expression = System.Linq.Expressions.Expression;
 
 
@@ -601,24 +602,21 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
         var otherids = rows.Select(r => r.Get<TEntity, Guid>(x => x.ID)).Where(x => x != targetid).ToArray();
         var otherids = rows.Select(r => r.Get<TEntity, Guid>(x => x.ID)).Where(x => x != targetid).ToArray();
         string[] others = rows.Where(r => otherids.Contains(r.Get<Guid>("ID"))).Select(x => x.ToObject<TEntity>().ToString()!).ToArray();
         string[] others = rows.Where(r => otherids.Contains(r.Get<Guid>("ID"))).Select(x => x.ToObject<TEntity>().ToString()!).ToArray();
         var nRows = rows.Length;
         var nRows = rows.Length;
-        if (MessageBox.Show(
-                string.Format(
-                    "This will merge the following items:\n\n- {0}\n\n into:\n\n- {1}\n\nAfter this, the items will be permanently removed.\nAre you sure you wish to do this?",
-                    string.Join("\n- ", others),
-                    target
-                ),
-                "Merge Items Warning",
-                MessageBoxButton.YesNo,
-                MessageBoxImage.Stop) != MessageBoxResult.Yes
-           )
+        if (!MessageWindow.ShowYesNo(
+                $"This will merge the following items:\n\n" +
+                $"- {string.Join("\n- ", others)}\n\n" +
+                $" into:\n\n" +
+                $"- {target}\n\n" +
+                $"After this, the items will be permanently removed.\n" +
+                $"Are you sure you wish to do this?",
+                "Merge Items Warning"))
             return false;
             return false;
 
 
         using (new WaitCursor())
         using (new WaitCursor())
         {
         {
             var types = CoreUtils.Entities.Where(
             var types = CoreUtils.Entities.Where(
                 x =>
                 x =>
-                    x.IsClass
-                    && !x.IsGenericType
+                    !x.IsGenericType
                     && x.IsSubclassOf(typeof(Entity))
                     && x.IsSubclassOf(typeof(Entity))
                     && !x.Equals(typeof(AuditTrail))
                     && !x.Equals(typeof(AuditTrail))
                     && !x.Equals(typeof(TEntity))
                     && !x.Equals(typeof(TEntity))
@@ -635,23 +633,22 @@ public class DynamicDataGrid<TEntity> : DynamicGrid<TEntity>, IDynamicDataGrid w
                         x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
                         x.PropertyType.GetInterfaces().Contains(typeof(IEntityLink))
                         && x.PropertyType.GetInheritedGenericTypeArguments().Contains(typeof(TEntity))
                         && x.PropertyType.GetInheritedGenericTypeArguments().Contains(typeof(TEntity))
                 );
                 );
-                foreach (var prop in props)
+                foreach (var prop in DatabaseSchema.LocalProperties(type))
                 {
                 {
-                    var propname = string.Format(prop.Name + ".ID");
-                    var filter = Core.Filter.Create(type);
-                    filter.Expression = CoreUtils.CreateMemberExpression(type, propname);
-                    filter.Operator = Operator.InList;
-                    filter.Value = otherids;
-                    var columns = Columns.None(type)
-                        .Add("ID")
-                        .Add(propname);
-                    var updates = ClientFactory.CreateClient(type).Query(filter, columns).Rows.Select(r => r.ToObject(type)).ToArray();
-                    if (updates.Any())
+                    if(prop.Parent is null
+                        || prop.Parent.PropertyType.GetInterfaceDefinition(typeof(IEntityLink<>)) is not Type intDef
+                        || intDef.GenericTypeArguments[0] != typeof(TEntity))
+                    {
+                        continue;
+                    }
+                    var filter = Filter.Create(type, prop.Name).InList(otherids);
+                    var columns = Columns.None(type).Add("ID").Add(prop.Name);
+                    var updates = ClientFactory.CreateClient(type).Query(filter, columns).Rows.ToArray(r => r.ToObject(type));
+                    if (updates.Length != 0)
                     {
                     {
                         foreach (var update in updates)
                         foreach (var update in updates)
-                            CoreUtils.SetPropertyValue(update, propname, targetid);
-                        ClientFactory.CreateClient(type).Save(updates,
-                            string.Format("Merged {0} Records", typeof(TEntity).EntityName().Split('.').Last()));
+                            prop.Setter()(update, targetid);
+                        ClientFactory.CreateClient(type).Save(updates, $"Merged {typeof(TEntity).Name} Records");
                     }
                     }
                 }
                 }
             }
             }