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 strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Return Cursor data from Private Data Session form 2

Status
Not open for further replies.

Rajesh Karunakaran

Programmer
Sep 29, 2016
542
MU
Dear all,

I have a main form A. This form calls another form B which uses Private Data Session. I have cursors in B with buffering activated. User will enter data in these cursors (through form B UI of-course). I need this data from B to be returned to A. But, the cursors created from B auto closes when form is released. Alternatively, if I create cursors in A and pass names to B (so that B can insert to them), those cursors are shown as not used within B (coz of Private Data Session?).

What would be the best way to return a table data from B (say, in temporary cursors) to form A?

Thanks
Rajesh
 
If you give A a private data session, and give B a default data session, then A and B will share the data session. This means that you can create the cursor in A and it will still be visible in B.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Rajesh said:
...those cursors are shown as not used within B (coz of Private Data Session?).

Yes, a private datasession means starting empty and new again, that form only sees in its datasession what it puts there. And no other form sees this datasession. It's private.

Mike recomends to you to give form B a default datasession instead. That way, yes, you can see what form A alrady has opened and all this datasessions current state is what form B starts with. It might not be working, if you need your private session for any reason.

Even if you need to stick to this, of course there is a way to share. If data of form B (of its private session and workareas) contributes to DBFs form A also has open, thos DBF changes of course also are seen in form A.

Are you using the private datasession for cursors only, not binding to any DBFs? Then these cursors and all data within them are gone, yes, they vanish together with the private datasession.

Chriss
 
Juat to elaborate on my reply, a "default data session" is not a global data session. Rather, it is the data session that was in force when the form was opened.

So if Form A has a private data session, with a DataSessionID of, say, 3, and Form A launches Form B, and if Form B has a default data session (that is if its DataSession property is set to 1), then Form B will also have a DataSessionID of 3. (Don't confuse the DataSession property with the DataSessionID property.)

If, on the other hand, Form B's DataSession property was set to 2 (private), then its DataSessionID would be something other than 3.

I hope this makes sense.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mark and Chriss,

Thank you for your inputs.

The form A has default data session and I can't make it Private it seems for various reasons. The form B in fact I want to use it generally, ie, it can be called from many forms for a general purpose. I made B as Private session because it opens a few tables which sometimes might have already been opened or not in the calling form, we wouldn't know. I am using DataEnvironment for tables used.
 
The form A has default data session and I can't make it Private it seems for various reasons.

That shouldn't matter. The important thing is for Form B to have a default data session. It will then "inherit" the data session of the calling form, whether that is default or private.

I made B as Private session because it opens a few tables which sometimes might have already been opened or not in the calling form, we wouldn't know.

Well, the usual solution to that would be to check to see if the table is open before trying to open it. Something like this:

Code:
IF NOT USED("MyTable")
  USE MyTable IN 0
ENDIF
SELECT MyTabe

If you do that when opening each table (or cursor) in Form B, then perhaps Form B wouldn't need a private data session (of course, there might be other reasons for Form B to have a private data session, other than it not knowing what tables are already open).

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
There is another solution, but it is a bit clumsy:

1. Give Form B a private data session (it doesn't matter about Form A's data session).

2. Create the cursor in Form A.

3. In Form A, when you are ready to launch Form B, have A pass its own DataSessionID as a parameter.

4. In Form B, at the point where you need to use the data from the cursor, temporarily store B's DataSessionID in a variable (or property); use SET DATASESSION to change B's data session to that of A; extract the data from the cursor; then change B's DataSessionID back to the saved value.

By "extract the data", I mean copying it to some other storage, such as variables, custom properties, an array or a collection (but not another cursor), which you then use in place of the cursor.

As I say, it's a bit clumsy, and it might not be suitable in this case, but it might be considering.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike,

I am using DataEnvironment for opening the tables and not by 'USE' commands. As you suggested, I can make the Data Session to Default and then check for all tables if they are opened or not and open them accordingly. I will save a flag for which were opened in this form and later close only those when I release the form. This way I can solve it I hope. Let me check that.

Rajesh
 
My feedback to changing from D tables to a series of conditional USE is: It's clmsy and won't cover all cases well.

Say form A uses a table t1 and moves to record N. Form B also needs this table t1, it is salready open, so it flags this was alreadyy open, so it doesn't close it when releasing, as it's needed by form A.

So far, so good, several problems are solved to have the necessary tables and keep them open as needed. But imagine form B wants to move in table t1 to another record M<>N.
Well, you can remember N and move back there. Where do you want to end with flags and remembered recnos?

And even if you do all that, the reality is form A works on exactly that table t1 and the pointer moved already cchanged things in form A. The User focussing form A while form B still runs will see this in effect, if t1 is shown in controls.

So the separation of datasessions has its benefit, even if you want to work on the same tables. You can still, it's the same DBFs, and what you change in the DF file comes across, without forwarding or returning a value, even.

The deecision whether two forms should work in the same datasession should be made if form B is such a form, that it extends the use case of form A and is just a separate form because you want to avaoid a pageframe and tabs to do the same within one form.

Here it's not that case, it seems, as form B can be called from many other forms, so it seems to be a general use case form.

I don't recommend changing form b to general datasession just for the case of form A, if there are further forms X,Y,Z that don't follow the saame pattern. You can return a whole table, too, if you use CURSORTOXML and then turn that XML back to a cursor/table. Or you simply store the cursor into a dbf and return the file name of that dbf, so form A can use it. Besides the "trick" Mike alreaddy recommended to know the datasessionid, you can switch to it and create a cursor there with all the data. And that's still not all ways to return more than one single value to form A, you can create an object and return that, with many properties to use, even a hierarchy of objects, you can use a collection or an array to trasnport lots of values.

Working in the same datasesssion on the same table or even on several shared tables can make sense, especially if you work on the same records of them, but it's a path that leads to applications only using the datasession id 1 and trying to manage all in one datasssion. This bcomes ugly fast.

Chriss
 
Hi Mike, Chriss,

Sorry for reporting late.
I did as follows:

From FormA (Default Data Session), calls FormB (made this also Default Data Session) as
Code:
DO FORM FormB WITH <total amount>, <Result_cursor_name>

In FormB
1. Checks if required tables are already opened or not, open table(s) if required (using USE command within the LOAD method)
and keeps flag for each table accordingly for open status.
2. Creates cursor for user entry (this involves tables which are already known to be open in FormA as well) using SELECT Sql.
3. Accepts all user entries and Save confirmation.
4. Upon saving, writes the contents of cursor in point 2 to the cursor names passed from FormA, ie <Result_cursor_name>.
5. Closes the cursor in point 2.
6. Closes those tables which are opened from within FormB (in UNLOAD method).
7. Releases and goes back to FormA

In FormA
1. User entries are received in <Result_cursor_name>
2. Further processes are started.

It works well.

Thank you,
Rajesh
 
The bullet list of things you do works out well, but depending on the result size, returning data with a switch of datasession as Mike suggested or returning XML you can turn into a cursor in the caller datasession are simpler solutions in terms of not interfering with the default datasession by using a private datasession.

While you solved it, I would rethink it, as this is an overall working but complicated pattern, if you start doing it this same way with all your forms. That will one day lead to a problem, if three forms are involved and you don't close forms in the same order as they are opened.

To illustrate herre's an example of three forms working in the same datasession.

Form 1 needs tables A,B,C
Form 2 needs tables C,D
Form 3 needs tables D,E

So there is an overlap.

Form 2 is started from Form 1 and notes table C was already open, so it only flags to close table D when it closes.
Form 3 is started from Form 1, too, and notices table D is already open, so it only flags to close table E when it closes.

Now if Form 2 closes, it closes table D and Form 3 has a problem.

The problem here is, that this kind of flagging does not take note of the needs of forms which are started after them. So your solution works fine for two forms of which you know the second form closes first, but the order of closing forms is not always necessarily the inverse of the order the user opens them. And there is no intelligent mechanism to look into the furture and manage the needs of all forms within one and the same datasession.

There's no question your need to create a cursor with the results in the datasession of the calling form speaks for working in the same datasession in this case but it's also not impossible to return just a list of IDs, for example, and then create that result cursor within the calling form. There are many more ways to do this, you could for example also return the query necessary to get the result and eecute it in the calling form, you can switch datasession in the called form and do it there for the caller, then switch back to the private session. I'd rather need to do one of all these things instead of programming flags of which tables to be responsible and which not.

In theroy a table manager class could be used to moderate between all forms which table is currently needed by how many forms, simply counting that, and only closing forms, of which the usage count drops to 0. It will still not be able to take care of the situation two forms need the same table, but need to navigate to different records within that table, then you need to use the table twice. It's possible with the AGAIN clause, but not with the same alias name. It gets more complicated the deeper you think about it. And while this flagging works in a two form situation most often, as the second form also closes first, even a to form situation can become complicated enough that this flagging solution doesn't cover all cases.

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top