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

Passing a cursor as a parameter

Status
Not open for further replies.

AndrewMozley

Programmer
Oct 15, 2005
621
GB
I have a function my_update() which updates several tables; it runs in its own data session.

The form which calls my_update() has built up a cursor, tdetail, which contains several lines (records) of information which need to be passed to this function.

What is the best way of doing this? Up to now I have taken the contents of tdetail and built them into an array, passing this as a parameter to my_update().

Thanks. Andrew
 
Andrew,

You don't need to do anything special to "pass" the cursor. Provided your function is running in the same data session as the form which created it, the cursor will already be available to the function.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Just to elaborate a little:

If you call a function or procedure (in a PRG file) from a class, the function or procedure will, by default, have the same data sesssion as the class. So you don't need to do anything special to make the cursor available.

The above is also true if you call another class (including a form), and that class's DataSession property is set to 1 - Default data session.

But if you call another class or form which has its own data session (DataSession = 2 - Private data session), then the cursor will not be visible. You can solve that by temporarily resetting the data session within the called class. In that case, you will have to pass the caller's DataSessionID as a parameter:

Code:
* In the caller
DO FORM MyPrivateDataSessionForm WITH THISFORM.DataSessionID

--------

* Init of MyPrivateDataSessionForm 
LPARAMETER tnSession

lnOldSession = SET("Datasession")
SET DATASESSION TO tnSession
* ----
* Do whatever you want to do with the cursor 
* ---
SET DATASESSION TO lnOldSession

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks Mike. However the form is running in its own data session, which is different to the data session in which the form is running.
 
(I sent my response while your second message came through) Thank you . I will do that.
 
Could you not just pass the name of the alias?
Code:
Select * from MyTable order by MyField into cursor MyCursor

MyFunction("MyCursor")

Function MyFunction
  Parameters MyAlias
  Private m.OldArea,MyAlias
  m.OldArea = Select()
  Select(MyAlias)
  Do while .not. eof()
    ? MyField
    skip
  Enddo
  Select(m.OldArea)
  Return(.t.)

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
It's more ideal to have such a functionality in the same data session.

When you call a PRG it will run in the same data session as the caller, which makes me wonder what differs in your situation. An object lives in the data session it's created in, but not a function or a PRG.

Let me verify what I claim:
Code:
o = CreateObject("mysession")
o.currentsession()
? fn_currentsession(), Set("Datasession")
o = .null.

Define Class mysession as session
   procedure currentsession()
      ? fn_currentsession(), Set("Datasession"), this.datasessionid
   endproc
EndDefine 

Function fn_currentsession()
   return Set("Datasession")

Indeed the fncurrentsession() function called is either in the same datasession as the object "o" or as the code of the default session, the function is not living anywhere, it's no object. Therefore it returns the same datasession id as the callee itself does and any pair of fn_currentsession() and Set("Datasession") is the same number. So you shouldn't have a problem and could just pass in the alias name to work on to your my_update.prg or my_update() function.

That said, even normal objects (ie objects based on the custom class) are living in some datasession, as demonstrated here:

Code:
Store .null. to o,o2,o3
o = CreateObject("mysession") && o creates mycustom as o2 within its init()
o3 = CreateObject("mycustom")
? "mysession:"
o.currentsession()
? "mycustom created from mysession:"
o2.currentsession()
? "mycustom created from code in default session:"
o3.currentsession()
? "fn and Set('Datasession') called from default session:"
? fn_currentsession(), Set("Datasession")
Store .null. to o,o2,o3

Define Class mysession as session
   Procedure init()
      o2=CreateObject("mycustom")
      
   procedure currentsession()
      ? fn_currentsession(), Set("Datasession")
   endproc
EndDefine 

Define Class mycustom as custom
   procedure currentsession()
      ? fn_currentsession(), Set("Datasession")
   endproc
EndDefine 

Function fn_currentsession()
   return Set("Datasession")

The o (mysession) object is starting its own new session, the o2 object created within it is also living in that session. The o3 object (also mycustom) created by the default session code is living in the default session.

The session number or datasessionid is not a property of every object, but still every object is in one. Otherwise controls wouldn't work, they are objects themselves and if they wouldn't be associated with the same datasession as the form and its dataenvironment they couldn't bind data of it, could they? So it's not a big surprise.

Therefore your my_update may either be a function or prg, when you do structural programming. My_update() could also be a method of a base class any related class inherits, so data maintenance or business logic objects live in the same datasession as the table(s) they maintain. In either case you don't have such problems. You only get such a problem if you put the my_update code inside one object that obviously can't live in all datasessions at the same time. You're breaking the encapsulation principle, if that's the case, but I don't think so.

I think you just never tried to access the same table or cursor within the function, which would be as easy as passing on the alias name as parameter tcAlias, and the SELECT (tcAlias) to select it and address fields of it, scan it or even query it with SQL.

Bye, Olaf.
 
Olaf said:
I think you just never tried to access the same table or cursor within the function, which would be as easy as passing on the alias name as parameter tcAlias, and the SELECT (tcAlias) to select it and address fields of it, scan it or even query it with SQL.

There you go...

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are not good for you.
 
Andrew said:
However the form is running in its own data session, which is different to the data session in which the form is running.
Are you talking of two forms in separate datasessions?

The same form started twice, perhaps? That would be harder to settle. If it's different forms and one (parent) always starts the other (child), then the child form can be set to the default session at design time already and thereby having the same datasession as the parent form creating it in any case.

In general, if you want two forms to work on the same record of some table you have two choices:
1. Start the second form in the same datasession and work with the already opened data. That's normal for such child forms I mentioned, which are always started from some parent form sharing the data. You'd put their datasession property to 1 - default session at designtime.
2. Just pass on IDs and let the second form reopen same tables and position on same records to see and work on the same data. An option for forms you also may want to start multiple times each working on some separate record, needing the same table with same alias name and different record pointer position, but they could also work on the same record, where it matters.

A cursor instead of the table complicates the situation, as it can't be reopened shared for a second time, then either create real DBF files instead of a cursor or go with option 1 to share the session.

Mike has given the third option to temporarily set to the other datasession. This option comes with some quirks, if at the same time controls are bound to form environment data, you can easily break controlsources. I would only do that datasession switching in mere data related and non visual classes/objects that rather are function libraries you init once and use from many places. That would not be true OOP style of development, but has some advantage over simple PRGs and/or sets of function definitions, as such an object could maintain a certain state in its properties, which influences its methods instead of needing that as parameter of all related functions or even worse instead of using a public variable to hold that value resembling some general setting.

Bye, Olaf.
 
Olaf

Thank you for your replies.

My second message was mistaken. I meant to say :

The form is running in its own data session, which is different to the data session in which the function is running.

There is only one form. Since the function my_update() is running in a separate data session (within an object, let us call it o_my_funcs) the cursor which the form created is not visible in my_update() unless I include an instruction to set the datasession. And this is what I shall do; I am happy with the solution that Mike has suggested.

Andrew
 
OK, so we are talking about an object which bundles some functions as methods and you really talk about calling o_my_funcs.my_update().

Another very simple solution then is to create one such object per form or make the datasession switching one of the methods of this class, which every form.activate then would call, for example, so any form always puts this object in its datasession. That would make that object universally usable, if the object itself does not need some cursor or tables it opens for its own purposes, of course. It would be switched away from them.

If you call these methods from forms only (or the controls within), you could also put the methods of this class into a base form class inherited by all other forms, then the call would become THISFORM.my_update(). That actually would be the main way to reuse code the oop way - by inheriting it.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top