Current filter:
                                You should refresh the page.
                                  • I need to have values of associated data items recalculate totals of their parent any time the associated data items amounts change.  See these classes.  This works perfectly when I run my XAF as Windows and fails when I run my XAF as a Web app.  I am trying to capture all the business logic in the business objects and not in controllers.  Is there a way to do this so that it works correctly in both Windows and Web?

                                        public class SMTimeCard : BaseObject
                                        {
                                            public SMTimeCard(Session session)
                                                : base(session)
                                            {
                                            }
                                             private DateTime _TimeCardDate;
                                            public DateTime TimeCardDate
                                            {
                                                get { return _TimeCardDate; }
                                                set { SetPropertyValue("TimeCardDate", ref _TimeCardDate, value); }
                                            }
                                            private double _TotalExpense;
                                            public double TotalExpense
                                            {
                                                get { return _TotalExpense; }
                                                set { SetPropertyValue("TotalExpense", ref _TotalExpense, value); }
                                            }
                                            public void Calc()
                                            {
                                                double totalexpense = 0;
                                                foreach (SMExpense SMExpense in SMExpenses)
                                                {
                                                    totalexpense += SMExpense.Amount;
                                                }

                                                TotalExpense = totalexpense;
                                                IObjectSpace objectSpace = XPObjectSpace.FindObjectSpaceByObject(this);
                                                objectSpace.CommitChanges();

                                            }
                                            [Association("SMTimeCardToSMExpense", typeof(SMExpense)), Aggregated]
                                            public XPCollection SMExpenses
                                            {
                                                get
                                                {
                                                    return GetCollection("SMExpenses");
                                                }
                                            }
                                        }
                                    ----------------------------------------------------------------------------------------------------
                                        public class SMExpense : BaseObject
                                        {
                                            public SMExpense(Session session)
                                               : base(session)
                                            {

                                            }
                                            double _Amount;
                                            public double Amount
                                            {
                                                get { return _Amount; }
                                                set
                                                {
                                                    SetPropertyValue("Amount", ref _Amount, value);
                                                    if (!IsLoading && SMTimeCard != null)
                                                    {
                                        SMTimeCard.Calc();
                                                   }
                                                }
                                            }

                                            private SMTimeCard _SMTimeCard;
                                            [Association("SMTimeCardToSMExpense")]
                                            public SMTimeCard SMTimeCard
                                            {
                                                get { return _SMTimeCard; }
                                                set { SetPropertyValue("SMTimeCard", ref _SMTimeCard, value); }
                                            }

                                        }

                                1 Solution

                                Creation Date Importance Sort by

                                Hello, Robert.

                                Please refer to the How to: Calculate a Property Value Based on Values from a Detail Collection article that explains how to solve this task.
                                As for your current solution, it is unclear what doesn't work in your Web XAF application. However, I suggest against using XPObjectSpace and calling CommitChanges from within a persistent object. I found that we discussed a similar task with you in the T598908 - XAF saving of data ticket where I provided similar recommendations. Do you have a strong reason to use this approach again?
                                Let me know if you face any difficult implementing the suggested solution.

                                • Robert Marks 10.18.2019

                                  Can you please clarify.  This example creates non-persistent results and then at the end of the example the non-persistent results are changed to become persistent results.

                                  Is this truly the only way to do calculations of Detail Collection if you know from the start you want the results to be persistent?  In my estimating section, my Detail Collections have their own Detail Collections so this goes about 4 levels deep.

                                  I don't see any ObjectSpace.CommitChanges. So if I make a change at level 4 that makes changes at level 3 and then level 2 and then level 1, this is still the correct way to do these calculations? And is nothing saved at any of the 4 levels until I click on a Save button on the forms?

                                • Michael (DevExpress Support) 10.21.2019

                                  Hello Robert,

                                  If you have multiple nesting levels in your XPO business object model, and all these levels are represented by aggregated properties, changes at intermediate levels are not saved to the database until the top level object is saved. When a user saves changes at an intermediate level, changes are "saved" in memory. To correctly update dependent properties at all levels, you need to recalculate them when any value on which the property depends is changed. That article demonstrates the recommended solution. The solution is similar for persistent and non-persistent dependent properties.

                                  If you wish the changes to be saved to the database immediately after modifying a nested level, do not use aggregation. However, then the user may need to refresh other opened views to get updated dependent values.