Quantcast
Channel: West Wind Message Board Messages
Viewing all articles
Browse latest Browse all 10393

Re: Load again

$
0
0
Re: Load again
FoxInCloud
Re: Load again
04/27/2012
09:50:36 AM
3HM0L3K9V Show this entire thread in new window
Gratar Image based on email address
From:
Tuvia Vinitsky
To:
Attachments:
None
This will NOT work. By resetting the recordsource, you are resetting the entire grid. The row cursor will go back to the top and there is a noticeable scroll. Grids can have thousands of records, this ruins the user interface.
------------
You have to reset the grid in wuserset once you remove that recordsource. I am glad now have the info, here is how I am putting it into my notes:

1. data opened in a form's init is executed when the session "opens" an existing form, but the data is scoped to the form not the session.

2. Since ueserset is called on every request, it can be used to manually reset the data to emulate as if it were scoped to the session.

3. There is a session object available that has setsessionvar and getsessionvar methods to set data sources or any other properties to be scoped to the session.

4. grids reset in wuserset still require redefining in code as if the recordsource was changed anywhere else

Question: given #3, why does FiC always recommned using the _screen object to hang session vars from?

I would still like to see multiple data set ability; wuserset is not a practical solution for an entire data set.


Just if your grid is populated on the fly, like assigning a .RecordSource while inlist(.ColumnCount, -1, 0)

If your grid columns are defined in the designer, it will have no effect AFAIK

Gilles would be more qualified than me to answer this question as he had to face it in his own FiC application (65 forms, 45 reports, PostGreSQL back end, in production for 6 months)

HTH,


then will I hae to recreate the grid column properties in wuserset every request?


Whether it is generated on the fly or not does not seem an issue to me.
You may store the table address into user's session by setSessionVar() and get it back at each request in .wUserSet().

Instead of querying a given permanent table for user-dependent data source, you can simply do this:

Procedure wUserSet thisForm.grid.RecordSource = space(0) USE IN SELECT('WebTemp') USE (m.Session.getSessionVar('tableName')) IN 0 ALIAS WebTemp thisForm.grid.RecordSource = 'WebTemp'

BTW, please avoid any public assumption on what I understand or not.


Neither I nor my co-developer understood your previous messages this way, and we still do not think you understand the issue. We do not know the name of the temp table, it is generated on the fly, and it has nothing to do with company. Each and every session has its own randomly generated dbf name. We do not understand how your example helps with that. tmp101 and tmp102 were examples, not names associated with something.

having to recode the entire grid is a separate issue.


As I attempted to explain you several times, here and by PM, FAS does indeed support this scenario provided you reUSE the proper table in .wUserSet():

PROCEDURE wUserSet lParameter tuUserID, tlTemp thisForm.grid.RecordSource = space(0) USE IN SELECT('WebTemp') LOCAL lcCompany lcCompany = Lookup(USERS.COMPANY, m.tuUserID, USERS.USERID, 'USERID') USE (iCase(; m.lcCompany = 'Company1', 'table1.dbf',; m.lcCompany = 'Company2', 'table2.dbf',; m.lcCompany = 'Company3', 'table3.dbf',; m.lcCompany = 'Company4', 'table4.dbf',; )) ALIAS WebTemp thisForm.grid.RecordSource = 'WebTemp'


IOW using an alais that could have different source tables is not supported.


As explained earlier, as it depends on the user, this should be done in wUserSet() rather that Init()
You need some table naming scheme based on userID, or table address stored in USERS table

Do you have it running with an alias> IOW

use tmp101.dbf alias webtemp
then the next user/session on Init issues
use trmp102.dbf alias webtemp
then the third user/session issues
use tmp103.dbf alias webtemp
? The problem is different sessions have the same alias with a different underlying dbf behind the alias.


Set('FILTER') is saved by awServer.prg!awAJAX.PropsSave_DS_cXML_Alias() and restored by awServer.prg!awAJAX.PropsRestore_DS_Aliases()
I see nothing in this code that could confuse dataSession with another.
To figure out how this 'issue' can occur, we lack details, e.g. debugger screenshots, trace, test case that we can reproduce.

We have FoxinCloud applications in production using SET FILTER without the issue you seem to report.


Thank you for the reply. However it is not enlightening me; I already understood about stateless. Every request must be accompanied by a recreation of all data by me. The whole point, as I understood, of FiC and data was that I could open tables, views, cursors, etc. on a form like I did in VFP, and FiC would manage the maintaining of the data with each request while the form is 'open".

I also understand that resetting a recordsouirce requires resetting all the column properties. That is hundreds of lines of code. In VFP there is an easy workaround for that, but not in FiC.

I also understand that I can requery views.

Unfortunately none of that answers my main question. I simply need to issue a SET FILTER TO against the currently open table. I can do all kinds of operations against tables and FiC properly restores the datasession. But set filter to causes the datasessions to get mixed up.


In any web application, data session needs be 'reconstructed', or 'restored' on each user request.
wConnect's basic principle is to always OPEN DATABASE and USE tables/views at the beginning of the request, and close them at the end.
This is called a 'stateless' server: each request writes on a new blank page.

FoxInCloud makes no exception to that principle, though it implements it slightly differently, very similar to regular form operation:

1- awFrm.Load() and/or DataEnvironment USE tables and views, probably NODATA

Form.Load() is executed once for all users, when the form instance is created for the server lifetime.
No difference with regular app operation: as .Load() accepts no parameter, coding user-based variations is very unlikely.

2- With Form.Init(parms) you can requery the views based on some parameters.
This only thing to take care of is to replace

parm1=value1 parm2=value2 Requery(myView)

by
thisForm.wViewParmSet(myView, 'parm1', value1) thisForm.wViewParmSet(myView, 'parm2', value2, .T.) && .T. triggers the actual requery()

This way FAS knows the view's parameters names and values, and is able to restore the view in the same state when user comes back for a new request.

Form.Init() is executed each time a user first needs a form, exactly like in regular LAN operation;
- parameters are passed as in normal LAN operation;
- .Refresh() is executed as in normal LAN operation.
The only difference is that the .Show() is not executed in Web mode. But awFrm.wFormShow() is executed, you can move your code there, and call this.wFormShow() from .Show().

3- awFrm.wUserSet(userID) allows you to adapt the form environment (including data) to user's profile - e.g. you may reUSE different tables or views based on userID, like in your scenario.
Care must just be taken with grids:

Grid.RecordSource = '' USE IN commonAlias USE currentUserTable/View ALIAS commonAlias Grid.RecordSource = 'commonAlias'

In this scenario is when you have a Grid with dynamically populated columns (not in the Class/Form designer) - As columns are destroyed when clearing Grid.RecordSource, you need to restore everything like .Header.Caption, .CurrentControl, etc.
[by the way, I think we could create a standard method for reUSEing an alias with a different table/view and take care of Grid(s).RecordSource and .Columns definitions]

awFrm.wUserSet(userID) is called at the very beginning of each request, before form state is restored, thus before any user event is executed.
awFrm.wUserGet() is called at the very end of each request
[All this can be seen in awAJAX.FormRequest() source code.]

You would probably move to awFrm.wUserSet(userID) the code you usually run in Form.Init() based on user ID.

This is a straight application of the 'stateless principle' we recalled at the beginning of this post: everything user-dependent must be restored on each request.

HTH,


there needs to be some way of emulating what Load does. for multi data sets, you want to initialize grid data sources before the grid initializes. if you have a private data session in the form, I see no way to do this. You can now create a data source in Load and update it in init, but that does not help this issue. I see no place to ever create a grid data source after the initial Load without a whole bunch of manual coding in the Init.

Multi data sets rely typically on the fact that there are X copies of the complete data set, each located in a unique location, but with the exact same data names and structures. Like deciding to drive a car down Highyway 1 or a parallel highway called Highway 1. Once on the highway, the car functions exactly the same. The 2 highways are parallel and never meet. Once on one of them you are committed to staying on that road.

Since forms are instatiated only once, it is like only having one highway. Therefore in the Init we have to build a new highway as we go by manually creating the grid. Yuck,













Viewing all articles
Browse latest Browse all 10393

Trending Articles