Another Beginner Easy Question

Another Beginner Easy Question

Old forum URL: forums.lhotka.net/forums/t/12876.aspx


MarkOverstreet posted on Monday, May 04, 2015

I'm trying to do something really basic.  I have a lookup table called TWageType and the structure is simply a description field containing 3 records (Hourly, Salary, Other).

I'm trying to create my first business object to simply allow me to retrieve all the records and bind them to a grid for admin maintenance.

So I have a WageType class inheriting from BusinessBase<WageType> and I have a WageTypes collection inheriting from BusinessBindingListBase<WageTypes,WageType>.  All works so far.

I have the following method in the WageTypes collection (list):

        public static async Task<WageTypes> GetAll()
        {
            return await DataPortal.FetchAsync<WageTypes>();
        }

and in the DataPortal_Fetch of the WageTypes collection (list) I have this...

        private void DataPortal_Fetch()
        {
           
            // get all the payment methods from the database.
            TWagePaymentMethods paymentMethods = TWagePaymentMethod.SelectAll();

           
            foreach (var item in paymentMethods)
            {
                WageTypes w = this.AddNew();
                w.Description = item.Description;

                //using (w.BypassPropertyChecks)
                //{
                //    DatabaseHelper.CopyProperties(item, m, string.Empty);
                //}

            }
        }

 

This appears to work but I have 3 questions. 

1)  The WageType object when created with .AddNew  has it's IsNew property set to true but in your example code in your eBook I didn't see any example of this unless I missed it.  IsNew should be false.  So what should I do?

2)  Why can't I do the BypassPropertyChecks like in your book.  If I uncomment this, the compiler complains that it isn't a property of the object.

3)  Is this even the correct way to do this?  My goal is simple,  load the values in a grid and let the user change them at will, add new ones, delete, etc.  Standard stuff.

Thanks again for any help.

Mark

JonnyBee replied on Monday, May 04, 2015

You have to understand the difference of a list object and the business object. 

Your DataPortal_Fetch is in the list object. BypassPropertyChecks is a property of the business object (item). 

If you look at the samples - typically the list will call this.Add(DataPortal.FetchChild<type>(param)) and this in turn calls the Child_Fetch method on the business object and will also make sure that the child object is marked as Old. 

When you call this.AddNew it is the same as when you insert new objects during edit of the list, 

So the semantics would be: 

        private void DataPortal_Fetch()
        {
            // get all the payment methods from the database.
            TWagePaymentMethods paymentMethods = TWagePaymentMethod.SelectAll();
            
            foreach (var item in paymentMethods)
            {
                this.Add(DataPortal.FetchChild<WageType>(item);
            }
        }

and in WageType class:

        private void Child_Fetch(TWagePaymentMethod data)
        {
                using (w.BypassPropertyChecks)
                {
                    // set properties in the bussiness obect from the supplied object from database
                    DatabaseHelper.CopyProperties(item, m, string.Empty);
                }
            }
        }


MarkOverstreet replied on Monday, May 04, 2015

Thanks!   That worked great but caused an interesting issue.  I loaded all 3 records into a grid and when the user types in a row to change an existing value in the RowUpdated event I get a reference to the underlying object for that row and I try to call

.Save

to save the modified description and I get an error that says {"Can not directly save a child object"}

So my goal is to bind the simple list of descriptions for this look up table to the grid so that the user can modify the value, tab off of the row, modify the second value, tab off the row, etc.  If I call save on the entire collection, first I will be serializing the entire contents across the wire when maybe only one object changed and also it seems like it will screw up the tabbing from row to row if I have to save the entire collection each time and rebind.  What am I missing?

Thanks again,  i really appreciate the help in trying to get going with CSLA.NET.

Mark

ajj3085 replied on Monday, May 04, 2015

You'd call Save on the BusinnessListBase class, which would save all the children at once.  this is the most normal case as a user will typically have a save button which saves all the changes to the form.  if you really want to save as the row loses focus, change your list to subclass DynamicRootListBase and change your child to be a root by implementing DataPortal_Fetch, _Insert _Create and _Insert, as appropriate.

MarkOverstreet replied on Tuesday, May 05, 2015

Hi Andy,

Thanks for the help.  I didn't see your DynamicRootListBase but I did try DynamicBindingListBase and it worked perfectly (and you knew it was coming) except for one issue that I'm hoping is simple to fix.

I can load the single column grid of descriptions, edit one and tab off and it even automatically calls the Save method on my individual objects for me (awesome) but the grid does not display and empty row at the bottom so that a user can add new descriptions.  On my BindSource that is bound to the grid I have set the property AllowNew to true and that didn't work.  I then added the AllowNew = true; in my constructor of my DynamicBindingListBase object which didn't appear to work either.    Any idea what I am missing to allow me to add new rows?

Thanks again.

Mark

MarkOverstreet replied on Tuesday, May 05, 2015

Never mind, I found the problem myself.  I'm using the DevExpress XtraGrid and forgot to set the NewItemRowPosition = Bottom.  Thanks again for the help it all works so far!

Copyright (c) Marimer LLC