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

XMLAdapter might load cursors in a different data session

Status
Not open for further replies.

Mike Lewis

Programmer
Jan 10, 2003
17,516
Scotland
I just came up against an interesting issue, and thought I'd share my findings.

If you call an XML Adapter's ToCursor() method, it doesn't necessarily create the cursors in the current data session. Rather, it creates them in the data session that was in force when the object was instantiated.

Consider this code:

Code:
DEFINE CLASS XMLStuff AS SESSION

oXML = NULL

FUNCTION Init
THIS.oXML = CREATEOBJECT("XMLAdapter")
ENDFUNC

FUNCTION GetData
* Receives the caller's data session as a param, 
* so that it can return the cursor to the caller
LPARAMETER tnSession
LOCAL lnOldSession

lnOldSession = SET("Datasession")
SET DATASESSION TO tnSession

* Do something here to get the XML (e.g. from
* a web service)

* Convert the XML to a cursor
WITH THIS.oXML
  .Load(lcXML)
  .Tables(1).ToCursor(.F., "SomeCursor")
ENDWITH 

SET DATASESSION TO lnOldSession

ENDFUNC

ENDDEFINE

The aim of this code is to encapsulate the XML management in its own class, and to return the results, in the form of one or more cursors, to the caller's data session.

As coded here, this will fail. The cursor's will be created in the class's own data session (because that's where the XML Adapter object was instantiated), and will be invisible to the caller.

It's easy to get round this. You can either instantiate the XML Adapter object after you do the data session switch. Or you can give the whole class a default data session. But you have to know about it -- and, as far as I know, this behaviour isn't documented, which is why I am posting it here.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
Hi Mike,

I think this is documented in a more general help topic. It's not limited to the Session class, that a class works in the session it was instaciated. You need to change the session from inside.

I suggest you run this in a seperate VFP IDE instance:
Code:
Clear All
Public oSession2,o1a,o2a,o1b,o2b

* o1a is created in session 1 (default)
o1a = CreateObject("mycustom")
* therfore this cursor will display in session 1:
o1a.createcursor("cursession1_a")

* creating a new datasession by a session object,
* this has no further role, it's simply a second session. 
oSession2 = CreateObject("Session")

* Now datasession 2 exists, we change datasession from outside to it:
Set Datasession To 2 && this exists because of oSession2

* Now we create objects in session 2:
* therfore this will display in session 2:
o2a = CreateObject("mycustom")
o2a.createcursor("cursession2_a")

Set Datasession To 1
* o1b and o1b.o again are created in session 1
o1b = CreateObject("mycustom")
o1b.addproperty("o",CreateObject("mycustom"))
o1b.o.createcursor("cursession1_b")

Set Datasession To 2
* o2b and o2b.o in session 2
o2b = CreateObject("mycustom")
o2b.addobject("o","mycustom")
o2b.o.createcursor("cursession2_b")

* back to 1:
Set Datasession To 1
* o2a still is in session 2 and creates cursors there:
o2a.createcursor("cursession2_c")

* only setting the session from inside changes the place cursors get created:
o1a.setsession(2)
* therfore this displays in session2
o1a.createcursor("cursession2_d")

o2a.setsession(1)
* and this displays in session 1
o2a.createcursor("cursession1_c")

* the same for B-objects:
o1b.setsession(2)
o1b.createcursor("cursession2_e")

o2b.setsession(1)
o2b.createcursor("cursession1_d")

* but their subobjects session depend on them
* being a real subobject (with parent proerpty pointing back to the parent)

* o1b.o is only an added property, therefor it is still in session 1
o1b.o.createcursor("cursession1_e")
* o2b.o is a child object, therefore it moved to session 1 as o2b moved to 1
o2b.o.createcursor("cursession1_f")

Define Class mycustom as Custom
   Procedure createcursor(tcAlias)
      Create Cursor (tcAlias) (id I)
   EndProc
   
   Procedure setsession(tnDatasession)
      Set Datasession To tnDatasession
   EndProc
EndDefine

If you open the datasession window afterwards you can see that session 1 contains cursors with name curSession1_X and session2 contains curSession2 cursors.

Bye, Olaf.
 
Thanks for that feedback, Olaf. That's an impressive piece of code, and a persuasive argument. I can't fault it.

I've always been aware of the general principle that an object's datasession is the one in force when the object is insantiated (unless you specifically give it a different one, as is usually the case with a Session object and often with a form).

I just didn't think of it as an issue with something like an XMLAdapter. I assumed that if you switched datasession in order to execute ToCursor(), the cursor would be created in that datasession. I spent a good half hour trying to figure it out this afternoon.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

My Visual FoxPro site: www.ml-consult.co.uk
 
I spent a good half hour trying to figure it out this afternoon.

I can feel with you.

Today I had the following case and didn't figure out why this happens: this.setfocus() in a controls lostfocus() works, I can see the eventchain is running via SET COVERAGE: valid, when (of next control), lostfocus (setfocus), when (of THIS), gotfocus but also finally a second valid. Finally the focus goes to the next control anyway.

Bye, Olaf.
 
Yes, that works. Thanks.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top