Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Passing an array or a cursor to a function in a separate data session

Status
Not open for further replies.

AndrewMozley

Programmer
Oct 15, 2005
621
GB
I am converting an accounting application which includes a function “Mypost” which updates several tables when an invoice for a customer is to be posted to the system.

In the original application, all of the tables were open during the whole session, so that the function Mypost could Append or Update records in the several tables as necessary.

However I have now put these functions into a session class :

Code:
DEFINE CLASS Myprocs AS SESSION
   FUNCTION MyPost(Param1, Param2 . . )
   . . .
   ENDFUNC

At the start of my main program, I instantiate this glass as a global object :
goProcs = NewObject(“MyProcs”, “Myproc.prg”)

Then when I want to call function My post, I write :
goProcs.MyPost(Param1, @Param2 . . .)

These parameters will be variables such as customer account, date &c or arrays such as the line details.

This works up to a point. I have two concerns :

1. Does it matter that this way of working could be considered mildly inefficient, since, for example, in Mypost() I may have to re-open the customer table, which was already open and positioned on the right record? Likewise does it matter that I believe I am opening and closing the tables (there are 6) each time I call MyPost().?

2. One of the parameters that I wish to pass over is a two-dimensional array of line details. In fact it is stored as a cursor tDetail (containing six fields) in the main program, but I believe that I need to make it into an array to pass it across as a parameter : MyPost(@aDetail, . . .). How do I then interpret it as a two-dimensional array in function MyPost(vDetail). At present I thought I was extracting (say) the second line of details by writing :

aLine = vDetail[2]

This executes OK, but when I try to extract a single field from this line, evaluating aLine[1], this error message is displayed :

File ‘aline.prg’ does not exist.

3. Even though MyPost() is running in a separate data session, could there still be some means of passing my original cursor tdetail across as a parameter?

Thank you all.



 
Andrew,

I'll have a crack at answering your questions:

1. Does it matter that this way of working could be considered mildly inefficient ...

It's a matter of opinion. It's true that it is inefficient to open and close tables in this way. But you are trading that against the benefit of keeping the class self-contained with its own data session. Personally, I would stick with the way you are doing it. No doubt others will have different opinions.

2. One of the parameters that I wish to pass over is a two-dimensional array of line details.

The problem is that the compiler doesn't know it's an array, so treats it as a function. The solution is to declare the array with an EXTERNAL command. See the VFP Help for an example.

3. Even though MyPost() is running in a separate data session, could there still be some means of passing my original cursor tdetail across as a parameter?


Yes. You can do this by passing the calling program's data session ID as a parameter. To find the caller's data session ID, use SET("DATASESSION"). Within the called function, save the current data session (that of your MyProc class) to a variable; set the data session to the ID that was passed as a parameter; access the cursor in question; and the set the data session back to what it was before. Something like this:

Code:
* Caller
lnID = SET("DATASESSION")
goProcs.MyPost(Param1, @Param2 . . .,  lnID)

* Called function
FUNCTION MyPost(Param1, Param2 . . , tnID)
LOCAL lnOldSession
lnOldSession = SET("Datasession")
SET DATASESSION TO tnID
.....
* Do whatever you want to do
....
SET DATASESSION TO lnOldSession
RETURN

The above isn't intended to be working code. It's just to give you the general idea.

Mike





__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Another point ....

You asked: Likewise does it matter that I believe I am opening and closing the tables (there are 6) each time I call MyPost().?

You don't have to open and close the tables each time you call the function. Only open a table if it is not already open. It will then remain open - even in subsequent calls to the function - until you explicitly close it or you destroy the object.

Regarding my answer to your third question, about passing the caller's data session ID as a parameter, and then switching to that data session within the called function. Keep in mind that any changes the called function makes to the data environment will affect the caller. So if the function changes the work area, for example, it will also be changing the work area of the caller. This is almost certainly not what you want. So in those cases, be sure to change these things back to the way they were before you finish.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
If you want to pass single records, it's much easier with objects, not arrays.

In the caller you can..
Code:
SCATTER NAME loCustomer MEMO
...and pass loCustomer to your MyProcs instance as paramater. loCustomer will have properties named the same as the cursor/table fields, so if you name the parameter as the table or alias it would even need no code change to address the fields, you're now just addressing properties of a object. You can only pass on single records in a single object. To send a whole table you'll need a collection holding many such objects. Another solution is to use CursorToXML and XMLToCursor.

What Mike suggests would work, but I'd judge it as dangerous to use a session class and then change the session, you would rather use another class like custom, then. I remember bad experiences with a session class switching it's SessionID in VFP7, where the situation was opposite: This session was mostly working with data the rest of the application didn't needed and which shouldn't convolute or influence form data sessions.

If you decide for a class being it's own session you shouldn't break the principle of a session not having any data access to other sessions. The outside world has to pass in whatever data you need or you stay with a dependency of some cursor/table being present for the class instance to work. This is a decision about the OOP encapsulation principle. A class used to retrieve data into cursors should of course do so in the data session of the caller, so a session switching then is absolutely ok and necessary. But a class taking input data from tables/cursors is causing doubt to me. Since this is where you're at it's fair to stay this way, as it worked so far, but in principle the outside world, much code of all the application classes and forms, will now need to pass in the data the code previously simply took from what was currently opened, if you really want to encapsulate the new class.

Bye, Olaf.
 
What Mike suggests would work, but I'd judge it as dangerous to use a session class and then change the session

I'm inclined to agree. I have done this myself (switching to the caller's data session), but only when I couldn't find an easier way. It's not something I would set out to do.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thank you both. I have in general adopted your suggestions, Mike. I have also chosen to open the tables in the Init() method of the class in which the function MyPost() is defined.

I agree that it seems quite complicated to pass the original datasession over to MyPost() and have stuck with treating the data as an array.

Olaf - I will experiment with passing a data record as an object. I am not familiar , but it time I learned !

Andrew
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top