Forráskód Böngészése

Improvements to GetValues() to exclude calculated columns, and improved digitalformdatamodel to use the same columns as the grid allows.

Kenric Nugteren 11 hónapja
szülő
commit
f08f31543c

+ 4 - 0
InABox.Core/BaseObject.cs

@@ -436,6 +436,10 @@ namespace InABox.Core
                 : default;
         }
 
+        /// <summary>
+        ///     Get all database values (i.e., non-calculated, local properties) for a given object <paramref name="sender"/>.
+        ///     If <paramref name="all"/> is <see langword="false"/>, only retrieve values which have changed.
+        /// </summary>
         public static Dictionary<string, object?> GetValues<T>(this T sender, bool all) where T : BaseObject
         {
             var result = new Dictionary<string, object?>();

+ 2 - 1
InABox.Core/DatabaseSchema/StandardProperty.cs

@@ -142,7 +142,8 @@ namespace InABox.Core
                     _calculated = Property.GetCustomAttribute<AggregateAttribute>() != null
                         || Property.GetCustomAttribute<FormulaAttribute>() != null
                         || Property.GetCustomAttribute<ConditionAttribute>() != null
-                        || Property.GetCustomAttribute<ChildEntityAttribute>() != null;
+                        || Property.GetCustomAttribute<ChildEntityAttribute>() != null
+                        || this.GetParent(x => x.IsCalculated) != null;
                 }
                 return _calculated.Value;
             }

+ 10 - 9
InABox.Core/DigitalForms/DataModel/DigitalFormDataModel.cs

@@ -216,17 +216,18 @@ namespace InABox.Core
             Dictionary<string, object?> variables = new Dictionary<string, object?>();
                 
             var formData = DigitalForm.DeserializeFormData(Instance);
-            foreach (var item in formData.Items())
-                variables[$"Data.{item.Key}"] = item.Value;
-                
-            var instancedata = Instance.GetValues(true);
-            foreach (var item in instancedata)
-                variables[$"Form.{item.Key}"] = item.Value;
+            if(formData != null)
+            {
+                foreach (var item in formData.Items())
+                    variables[$"Data.{item.Key}"] = item.Value;
+            }
                 
-            var entitydata = Entity.GetValues(true);
-            foreach (var item in entitydata)
-                variables[$"{typeof(TEntity).EntityName().Split('.').Last()}.{item.Key}"] = item.Value;
+            foreach (var property in DatabaseSchema.Properties(Instance.GetType()).Where(x => !x.Name.StartsWith("Parent.")))
+                variables[$"Form.{property.Name}"] = property.Getter()(Instance);
                 
+            foreach (var property in DatabaseSchema.Properties(Entity.GetType()))
+                variables[$"{typeof(TEntity).Name}.{property.Name}"] = property.Getter()(Entity);
+
             var exp = new CoreExpression(expression);
             return exp.Evaluate(variables)?.ToString();
         }

+ 6 - 0
InABox.Core/DigitalForms/Forms/DigitalForm.cs

@@ -130,6 +130,9 @@ namespace InABox.Core
         /// Takes a serialized FormData string and BlobData string and deserializes into one dictionary.
         /// The result of this is just as if you were deserializing formData as per usual.
         /// </summary>
+        /// <remarks>
+        ///     Returns <see langword="null"/> if <paramref name="formData"/> is not a valid JSON object.
+        /// </remarks>
         /// <param name="formData"></param>
         /// <param name="blobData"></param>
         /// <returns></returns>
@@ -148,6 +151,9 @@ namespace InABox.Core
         /// Like <see cref="DeserializeFormData(string, string?)"/>, but takes the FormData and BlobData from <paramref name="form"/>,
         /// rather than having to specify them manually.
         /// </summary>
+        /// <remarks>
+        ///     Returns <see langword="null"/> if <c>form.FormData</c> is not a valid JSON object.
+        /// </remarks>
         /// <param name="form"></param>
         /// <returns></returns>
         public static DFLoadStorage? DeserializeFormData(IDigitalFormInstance form)

+ 22 - 23
inabox.database.sqlite/SQLiteProvider.cs

@@ -610,11 +610,12 @@ namespace InABox.Database.SQLite
                 var cascadeFields = new List<string>();
 
                 var props = DatabaseSchema.RootProperties(otherType)
-                    .Where(x => x.IsEntityLink 
+                    .Where(x => x.IsEntityLink
                                 && x.PropertyType.GetInterfaceDefinition(typeof(IEntityLink<>))?.GenericTypeArguments[0] == type
-                                && !x.HasAttribute<ChildEntityAttribute>());
+                                && !x.IsCalculated);
                 foreach(var prop in props)
-                {                    var fieldname = $"{prop.Name}.ID";
+                {
+                    var fieldname = $"{prop.Name}.ID";
                     if(prop.GetAttribute<EntityRelationshipAttribute>() is EntityRelationshipAttribute attr
                         && attr.Action == DeleteAction.Cascade)
                     {
@@ -2294,28 +2295,24 @@ namespace InABox.Database.SQLite
             if (item.ID == Guid.Empty)
                 item.ID = Guid.NewGuid();
 
-            Dictionary<string, object> insert = item.GetValues(true);
-            Dictionary<string, object> update = item.GetValues(false);
+            var insert = item.GetValues(true);
+            var update = item.GetValues(false);
 
             var insertfields = new List<string>();
             var insertvalues = new List<string>();
             var updatecommands = new List<string>();
 
             var iParam = 0;
-            foreach (var key in insert.Keys)
+            foreach (var (key, v) in insert)
             {
-                if (insert[key] is UserProperties)
-                    continue;
-
-                if (DatabaseSchema.Property(T,key)?.Parent?.GetAttribute<ChildEntityAttribute>() != null)
+                if (v is UserProperties)
                     continue;
 
-
                 var sParam = string.Format("@p{0}", iParam++);
                 object? value = null;
                 try
                 {
-                    value = Encode(insert[key], insert[key]?.GetType());
+                    value = Encode(v, v?.GetType());
                 }
                 catch (Exception e)
                 {
@@ -2333,17 +2330,19 @@ namespace InABox.Database.SQLite
                         updatecommands.Add(string.Format("[{0}]={1}", key, sParam));
             }
 
-            var particles = new List<string>();
-            particles.Add("INSERT INTO");
-            particles.Add(T.EntityName().Split('.').Last());
-            particles.Add("(");
-            particles.Add(string.Join(",", insertfields));
-            particles.Add(")");
-            particles.Add("VALUES");
-            particles.Add("(");
-            particles.Add(string.Join(",", insertvalues));
-            particles.Add(")");
-            if (updatecommands.Any())
+            var particles = new List<string>
+            {
+                "INSERT INTO",
+                T.EntityName().Split('.').Last(),
+                "(",
+                string.Join(",", insertfields),
+                ")",
+                "VALUES",
+                "(",
+                string.Join(",", insertvalues),
+                ")"
+            };
+            if (updatecommands.Count != 0)
                 particles.Add("ON CONFLICT([ID]) DO UPDATE SET " + string.Join(", ", updatecommands));
             else
                 particles.Add("ON CONFLICT DO NOTHING");

+ 2 - 1
inabox.wpf/DigitalForms/Designer/Controls/DynamicFormFieldControl.cs

@@ -90,7 +90,8 @@ namespace InABox.DynamicGrid
         protected override void AfterSetControl(TField control)
         {
             base.AfterSetControl(control);
-            if (!string.IsNullOrWhiteSpace(control.Properties.Expression) && control.Properties.ReadOnlyProperty)
+            if (!string.IsNullOrWhiteSpace(control.Properties.Expression)
+                || (!control.Properties.Property.IsNullOrWhiteSpace() && control.Properties.ReadOnlyProperty))
             {
                 IsEnabled = false;
             }

+ 1 - 1
inabox.wpf/DigitalForms/DigitalFormGrid.cs

@@ -395,7 +395,7 @@ namespace InABox.DynamicGrid
                     var appliesTo = items?.Select(x => x.AppliesTo).Distinct().SingleOrDefault();
                     if (!appliesTo.IsNullOrWhiteSpace() && DFUtils.GetFormInstanceType(appliesTo) is Type instanceType)
                     {
-                        foreach(var property in DatabaseSchema.Properties(instanceType).Where(x => !x.Name.StartsWith("Parent")))
+                        foreach(var property in DatabaseSchema.Properties(instanceType).Where(x => !x.Name.StartsWith("Parent.")))
                             variables.Add($"Form.{property.Name}");
                     }