Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss. print.

A One To Many CA Example Form
For a start you will have to create a base CA class and 2 CA’s based on this for the CUSTOMERS and ORDERS tables as described in my Tut #2.
Create a new form and add the CA’s to the form’s DE as described. Make sure that the builder for the form DE looks like this:

Use Existing connection handle must be on and enter the name of the connection you will use. I use oConn. On the next tab just set the 2 CA’s as described in the tut as below:

- Use DE datasource is ticked.
- Name the CA’s as CACUSTOMER and CAORDERS.
- Close and save.

Drag and drop each CA from the DE onto the form to create 2 grids. These will be named (by default) grdCrsCustomer and grdCrsOrders. Add a button as shown and in its click code add this: (purists please note I cobbled this up very quickly so no niceties as declaring the vars etc.)

bb=INPUTBOX("Enter a single alphabet.(eg. C)")
THISForm.custid = ALLTRIM(bb)

As you will see from the code above there is still a bit to be done.

- Add a property to the form – custid.
- Add a method to the form – filldata

This is the code in FILLDATA()

WITH Thisform.dataenvironment.caCustomer
    This.grdCrscustomer.RecordSource = ""
    .lnodataonload = .F.
    .cfilterClause = [customerid like ']+THISForm.custid+[%']
    IF !.CursorFill()
        MESSAGEBOX(aErMsg[2],16,"SQL Error",0)
    This.grdCrscustomer.RecordSource = "crsCustomer"
WITH Thisform.dataenvironment.caOrders
    .lnodataonload = .F.
    .cfilterClause = [orders.customerid like ']+THISForm.custid+[%']
    .cSelectCmd = [SELECT Orders.* from orders]
    This.grdorders.RecordSource = ""
    IF !.CursorFill()
        MESSAGEBOX(aErMsg[2],16,"SQL Error",0)
    This.grdorders.RecordSource = "crsOrders"

Couple of things more
In the AfterRowColChange Event of the grdCrsCustomer add this code that will be run whenever you click on a new row:

Custid = crsCustomer.customerid
ThisForm.grdorders.RecordSource = ""
WITH ThisFOrm.dataenvironment.caOrders
    .cFilterClause = [orders.customerid like ']+custid+[%'] 
ThisForm.grdorders.RecordSource = "crsOrders"

Lastly you can either add a prg to run this form and put this code in it or open the DE of the form and in the BeforeOpenTables event add this code:

* use your server name instead of the ZFS04
oConn=sqlstringconnect([Driver={Sql Server}; Server=zfs04;Database=Northwind;Int Security;])

Please note that if you open the builder of the DE again and save it, this code just added will be overwritten by the builder. Also the sqlconnect is on one line!

oConn=sqlstringconnect([Driver={Sql Server}; Server=zfs04;Database=Northwind;Int Security;])

Now all that is left is to set your Default dir to the location where you unzipped these files (so that the form can find the classes) and run the form.

If all is well you will have 2 blank grids and no errors. Also 2 blank cursors have been created. Click Search and enter an alphabet “A” (without quotes) and you will see the grids fill with data. Click on the records of the upper grid and the bottom grid data will change.

Voila! 1 to many.

This data is fully updatable. If you set the BufferModeOverride property of the CA’s then if you make a change and move to the next record, a TABLEUPDATE() is run, or you can leave the property to 5 and run a TABLEUPDATE(1,.F.) to update the whole table. Remember to include the Alias or only the currently selected table will be updated.

This is only an example. In reallife apps., you will NEVER EVER do a SELECT * especially on a client table. Your search should just bring down a single client record and the related orders for that client.

I have included the source code for this form with this document. Please examine the methods and properties set and refer back to tutorial 1 & 2.

Download code
Click here to download the code that is discussed in this article. The download is a zipfile. Its size is 9,295 bytes.


Bernard Bout Bernard Bout is a long time member of the Foxite.COM Community and based in Brisbane, Australia. Bernard's weblog is here: http://weblogs.foxite.com/bernardbout/


noex Palic @ 2/3/2013 4:03:13 PM
Very nice Mr. Bernard! I tried your simple CA and it works, i used mysql as my backend. thanks a lot! :)

Your Name: 
Your Feedback: 

Spam Protection:
Enter the code shown: