I am very close to running my application in production, however, in tests with my team, I am facing some problems with simultaneous access in COM mode. If 2 users perform actions at the same time, this is showing me an ajax error. In file mode this problem does not occur. Does anyone have any idea what it might be? I'm uploading a video of the error.
&& Click Button code
LPARAMETERS nButton, nShift, nXcoord, nYcoord && Implementation documentation: see code inherited from aw.vcx!aw???.Click() (click 'View Parent Code')
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen) && Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 16:23
RETURN .T. && Process event on server (your code after this IF ... ENDIF block)
ENDIF && Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 16:23
WITH thisform
IF !thisform.metodo_pad.conecta_banco(.T.)
RETURN .F.
ENDIF
.forpag_id_caixa1 = CURREC.ID
.descricao_caixa1 = CAST(NVL(thisform.combobox_padrao1.DisplayValue,"") as M)
.desctipfor_caixa1 = CAST(NVL(thisform.combobox_padrao2.DisplayValue,"") as M)
IF .sel = 1 && Ver pq se da certo
.tipfor_caixa1 = 1
.desctipfor_caixa1 = "ENTRADA"
*.forpag_id_caixa1 = 1
ELSE
.tipfor_caixa1 = ICASE(SUBSTR(.desctipfor_caixa1,1,1) = "E",1,SUBSTR(.desctipfor_caixa1,1,1) = "S",2,0)
.desctipfor_caixa1 = ICASE(SUBSTR(.desctipfor_caixa1,1,1) = "E","ENTRADA",SUBSTR(.desctipfor_caixa1,1,1) = "S","SAIDA","")
ENDIF
IF NVL(.forpag_id_caixa1,0) = 0
thisForm.wMessageBox('', "Informe a forma de recebimento",48,"Atenção")
thisform.combobox_padrao1.SetFocus()
RETURN .F.
ENDIF
IF EMPTY(.descricao_caixa1)
thisForm.wMessageBox('', "Informe a forma de recebimento",48,"Atenção")
thisform.combobox_padrao1.SetFocus()
RETURN .F.
ENDIF
IF EMPTY(.desctipfor_caixa1)
thisForm.wMessageBox('', "Informe se é uma entrada ou saida",48,"Atenção")
thisform.combobox_padrao1.SetFocus()
RETURN .F.
ENDIF
IF NVL(.tipfor_caixa1,0) = 0
thisForm.wMessageBox('', "Informe se é uma entrada ou saida",48,"Atenção")
thisform.combobox_padrao1.SetFocus()
RETURN .F.
ENDIF
IF NUM_STR(thisform.textbox_padrao5.Value,10,2,"N") <= 0 &&thisform.teXTBOX_PADRAO5.Value <= 0
thisForm.wMessageBox('', "Informe o valor corretamente",48,"Atenção")
thisform.textbox_padrao5.SetFocus()
RETURN
ENDIF
IF .alteracao = .F.
.atualizaitens(1)
.limpaitens()
ELSE
.atualizaitens(2)
.gRID_padrao1.Enabled = .T.
.limpaitens()
.alteracao = .F.
.combobox_padrao1.Enabled = .T.
ENDIF
IF thisform.sel = 1
.somafom()
ENDIF
.gRID_padrao1.Refresh()
.combobox_padrao1.SetFocus()
ENDWITH
&& Atualizaitens Method
LPARAMETERS __opc && 1 para incluir e 2 para atualizar
WITH thisform
LOCAL M.ID AS Integer
IF __opc = 1
SELECT CRCAIXA1
APPEND BLANK IN CRCAIXA1
M.ID = thisform.metodo_pad.gera_id("caixa1_id_seq")
ELSE
M.ID = CRCAIXA1.ID
ENDIF
REPLACE ;
DESCRICAO WITH .descricao_caixa1,;
DESCTIPFOR WITH .desctipfor_caixa1,;
TIPFOR WITH .tipfor_caixa1,;
VALFOR WITH NUM_STR(thisform.textbox_padrao5.Value,10,2,"N"),;
OBSCAI WITH thisform.textbox_padrao3.Value, ;
FORPAG_ID WITH .forpag_id_caixa1,;
ID WITH M.ID ;
IN CRCAIXA1
ENDWITH
&& Limpaitens method
thisform.combobox_padrao2.Value = "ENTRADA"
thisform.combobox_padrao2.DisplayValue = "ENTRADA"
THISFORM.TEXtbox_padrao3.Value = ""
IF thisform.wlWeb = .F.
thisform.textbox_padrao5.Value = 0.00
thisform.textbox_padrao5.InputMask = "9,999.99"
ELSE
thisform.textbox_padrao5.Value = "0.00"
thisform.textbox_padrao5.InputMask = ""
ENDIF
Hi Arcadio
Congratulation for going to production!
From what I can see (video a little blurred), the error occurs in one of your programs. Please share the full error text so that we can discuss:
use wwRequestLog
browse for error
go bottom
&& locate the error near the end of the log
_cliptext = queryStr
&& the paste here
Thanks! Without help from everyone here on the forum this would not be possible. As for the problem, I realized that it is related to _screen.handle, since the same value is different between users and this is related to the connection to the database. Is there any treatment that I should do specifically for objects _screen ?
The error occurs exactly in this method below where the _screen is different between users.
thisform.metodo_pad.gera_id()
LPARAMETERS __NOMESEQ
DO CASE
USE IN SELECT("MAXIMO")
CASE ALLTRIM(_screen.tipobanco) = "POSTGRESQL"
LOCAL M.INSTRUCAOSQL AS String
TEXT TO M.INSTRUCAOSQL NOSHOW
SELECT CAST(NEXTVAL(?__NOMESEQ) AS CHAR(13)) AS NEXTVAL
ENDTEXT
M.FEZ = SQLEXEC(_screen.handle,M.INSTRUCAOSQL,[MAXIMO])
RETURN VAL(MAXIMO.NEXTVAL)
CASE ALLTRIM(_screen.tipobanco) = "SQL SERVER"
LOCAL M.INSTRUCAOSQL AS String
TEXT TO M.INSTRUCAOSQL NOSHOW
SELECT SEQ + 1 AS SEQ FROM SEQUENCIA TABLOCK WHERE TABELA = ?__NOMESEQ
ENDTEXT
M.FEZ = SQLEXEC(_screen.handle,M.INSTRUCAOSQL,[MAXIMO])
M.FEZ = SQLEXEC(_screen.handle,[UPDATE SEQUENCIA SET SEQ = ?MAXIMO.SEQ WHERE TABELA = ?__NOMESEQ])
RETURN MAXIMO.SEQ
ENDCASE
awajax.lSuccess(.f.): Error detected at code line #[no, av of method 'awajax.useraction' "FoxInCloud could not process this request: Awajax.useraction() - Error while executing method 'cad_atend1_scx.button_padrao3.Clickinet()': Method or procedure atualizaitens(): error #9 ("Data type mismatch") at code line #0 Parameters received:
- Value : -N/A-
- Object : button_padrao3 > Event: click > Property: none > Method: none" Call stack: 1 .processhit > 2 .process > 3 .routerequest > 4 easyprocess.process > 5 wwprocess.process > 6 easyprocess.domevent > 7 easyprocess.ajaxformrequest > 8 awajax.formrequest > 9 awajax.useraction
Exe: "C:\seazure\easylabwebfoxpro\easytest.exe", version 1.0.1397 of 2020-02-28 02:15:44 PM (4 hours ago) Process ID: 16628 Client: 189.69.166.140 userID: 5NM0PNJJX URL: http://portal.softeasy.com.br:81/easytest/DOMEvent.easy?&Event=click&ObjAddr=cad_atend1_scx-button_padrao3&UserID=5NM0PNJJX&PageInit=&nReq=57 Form variables: nKeyCode=, nButton=1, nShiftAltCtrl=0, nXcoord=508, nYcoord=165, nRow=1178, nCol=538, lastKey=13, version=2.29.0, sync=false, vpw=1381, vph=686, userID=5NM0PNJJX, reqID=1309_5PJ12EH5P-001, nInet=0.000, nCli=0.008 FAS version: 2.29.0 of 2019‑06‑06 12:05:12 PM GMT (8 months ago) Table New: 'C:\tempfic\5NM0PNJJX_5nm0pnjjx_cad_atend1_scx_New.DBF' can't be found
If I remove a part where it passes through the _screen.handle leaving a fixed value the problem does not occur
Arcadio,
You need to use one handle per server, shared by every users; make sure to set _screen.handle
in xxxSets.init()
and keep it unchanged; you can exclude it from the custom _screen.properties
that FoxInCloud saves automatically for each user like this:
define class xxxServer as awServer
…
_ScreenPropertiesSaveNot = 'handle, …'
Please read the documentation on _ScreenPropertiesSave
and _ScreenPropertiesSaveNot
in xxxServer.prg
All your remote views or CAD share the same _screen.handle
; eg. with views:
procedure dataEnvironment.OpenTables
…
USE v_ordonnance IN 0 NODATA AGAIN CONNSTRING(_screen.handle) SHARED
…
Gilles has used this technique against a PostGre Database without any issue for almost 10 years.
Cheers
The "handle" property is created in xxxinit and it has different values ??between users. Do I need to inform her in _ScreenPropertiesSave? I had understood that this was not necessary. Only if it has the same value among users should it be informed in _ScreenPropertiesSaveNot. Is my thinking correct or not? Follow below my xxxinit.
* =====================================================
DEFINE CLASS easySets as awSets of awPublic.prg && Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/03/2018 10:40
* =====================================================
&& This class is the standard implementation of application environment setting code.
&& FoxInCloud RECOMMENDS using a class as its .Destroy() method restores
&& the development environment, thus respect each developer's preferred settings.
&& If you prefer a procedural implementations, see down this file for more details.
&& If you prefer a procedural implementations, see down this file for more details.
&& To start your test FoxInCloud server, type in your Command Window:
* do <path to>easyTest
* ---------------------
PROCEDURE Init
lparameters ;
result; && @ result of application startup - appears in .../foxincloud-status.xxx, and in server log if !m.success
, toAppHost as awAppHost of awAppHost.fxp && Application Host object (Web mode only)
* toAppHost gives you access to:
* - any PROTECTED property you've added to your server class - see class easyServer in easyServer.prg
* - you application's configuration object in m.toAppHost.oConfigApp - see class easyAppConfig in easyServer.prg
* - many other properties and methods that you can discover by setting a break point and typing 'm.toAppHost.' to trigger intellisense
* HINT: In your code, you may take advantage of the following properties and methods:
#if .F. && documentation
this.wlWeb && application runs in Web mode
this.wlLAN && (this.wlLAN = !this.wlWeb) application runs in LAN (desktop) mode
this.lDevMode && application runs in the IDE
this.lAutomation && App works in COM mode (this.wlWeb only)
#endif
local success as Boolean
success = DoDefault(@m.result) && IMPORTANT! sets the above properties
if !m.success
return .f.
endif
* PLEASE NOTE
* --------------------------------------------------------------------------------------------
* FoxInCloud Adaptation Assistant has recycled the following code from
* 'c:\seazure\easylabwebfoxpro\prg\inicio.prg'.
* This code has the main configuration features for your application.
* You probably need to review it to operate correctly in Web mode,
* especially regarding the PATHes and tests specific to LAN mode.
* Note: the awPublic.prg!wlWeb() function indicates if application runs in Web mode.
* --------------------------------------------------------------------------------------------
* If you perform a new installation after some manual modifications,
* FoxInCloud Adaptation Assistant will detect it and propose to check
* and/or save the file before eventually replace it
* --------------------------------------------------------------------------------------------
* If anything serious happens during class initialization, set:
* success = .F.
* result = [the reason(s) why environment could not be set and/or application should not start]
* in Web mode, this error will get written into the application log, and a mail sent to administrator.
* in LAN mode, you could do something similar
* Before this code executes, FoxInCloud Application Server has set CurDir() to
* the application's main folder, where project resides
* (C:\seazure\easylabwebfoxpro\)
* All the following pathes are relative to this folder …
*SET STEP ON
SET PATH TO ".\CLASSE\;.\FIGURA\;.\FORM\;.\IMG\BMP\;.\IMG\ICO\;.\MENU\;.\PRG\" ADDITIVE
SET PATH TO ".\_Libs\xfrx\" ADDITIVE
IF !InList(_VFP.StartMode, 2, 3, 5) && In COM automation mode, Visual FoxPro implicitly performs a SET PROCEDURE and a SET CLASSLIB to the entire server by default when you instantiate an .exe or .dll COM server - if you reissue SET PROC or SET CLASSLIB repeatedly, COM object performance will drop sharply
SET PROCEDURE TO acessoftp,conecta,conecta_interface,figuras,foxbarcode,ftp,funcao,gpimage2,inicio,inicio_appse,inicio_fila,inicio_interface,inicio_libexa,inicio_sms,inicio_soroteca,inicio_triagem,menunew,registry,setobjrf,som,vfptranslator,zip,menufic,utilityreportlistener ADDITIVE
ClassLibAdd("_base.vcx,_controls.vcx,_webview.vcx,_ws3client.vcx,ambiente.vcx,barra.vcx,dados.vcx,foxcharts.vcx,lanca.vcx,laudo.vcx,msoexp.vcx,padrao.vcx,rtfbar.vcx,sfmenu.vcx,systray.vcx,termo.vcx,themedtitlebar.vcx,themedtitlebarbase.vcx,treeview.vcx,txtext"+"control19.vcx,vfp-skin2.vcx,easy.vcx") && modify command abDev
EXTERNAL PROCEDURE ClassLibAdd
ENDIF
PUBLIC M.VERSAOEL, M.VERMAJOR AS Character, M.VERMINOR AS Character, M.VERREV AS Character && Variaveis que informam qual é a versao do sistema
PUBLIC M.VISUEMTELA AS Boolean && Variavel para ser usada pela visualizacao do mapa de trabalho
PUBLIC oPARAM && Objeto com as configuracoes gerais do sistema
PUBLIC _prot && Objeto de protecao do sistema
PUBLIC oMENS && Objeto para exibir corretamente a barra de informacoes no rodapé do sistema
PUBLIC M.VERSAOEL && Variavel que informa qual é a versao do sistema
PUBLIC M.DATLICATU && Data atual em que a licença do sistema se expira
PUBLIC M.oFOXBARCODE
PUBLIC oMENU && Objeto com as propiedades do menu
PUBLIC M.FIGLAUDO
LOCAL M.TITPROG as String, M.IDPARAM AS Integer
PUBLIC oOPERADOR AS Object
PUBLIC M.OBARRA as Toolbar
PUBLIC m.OBJMENU as Object
PUBLIC M.ID_ATU
PUBLIC M.PATHTMP
*M.ID_ATU = NULL
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/02/2018 19:57
*-FIC- (see above) SET PATH TO (Home(1) + 'Tools\' + 'AB\') ADDITIVE
*-FIC- (see above) AB() && loads FoxInCloud public modules located in the above folder, and shared on GitHub: https://github.com/FoxInCloud/FoxInCloud-AB.git
*-FIC- (see above) SET CLASSLIB TO (Addbs(JustPath(Sys(16))) + '..\CLASSE\EASY.VCX') ADDITIVE && easy.vcx derives from aw.vcx
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/02/2018 19:57
&& /!\ make sure all SET PATH/LIBRary/CLASslib/PROCedure
&& executed after this line have the ADDITIVE clause
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/02/2018 10:06:32
*-FIC- (see above) SET PATH TO (Home(1) + 'Tools\' + 'AB\') ADDITIVE
*-FIC- (see above) AB() && loads FoxInCloud public modules located in the above folder, and shared on GitHub: https://github.com/FoxInCloud/FoxInCloud-AB.git
*-FIC- (see above) SET CLASSLIB TO (Addbs(JustPath(Sys(16))) + '..\CLASSE\EASY.VCX') ADDITIVE && easy.vcx derives from aw.vcx
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/02/2018 10:06:32
&& /!\ make sure all SET PATH/LIBRary/CLASslib/PROCedure
&& executed after this line have the ADDITIVE clause
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 19:18:49
*-FIC- (see above) SET PATH TO (Home(1) + 'Tools\' + 'AB\') ADDITIVE
*-FIC- (see above) AB() && loads FoxInCloud public modules located in the above folder, and shared on GitHub: https://github.com/FoxInCloud/FoxInCloud-AB.git
*-FIC- (see above) SET CLASSLIB TO (Addbs(JustPath(Sys(16))) + '..\CLASSE\EASY.VCX') ADDITIVE && easy.vcx derives from aw.vcx
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 19:18:49
&& /!\ make sure all SET PATH/LIBRary/CLASslib/PROCedure
&& executed after this line have the ADDITIVE clause
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
*-FIC- (see above) SET PATH TO (Home(1) + 'Tools\' + 'AB\') ADDITIVE
*-FIC- (see above) AB() && loads FoxInCloud public modules located in the above folder, and shared on GitHub: https://github.com/FoxInCloud/FoxInCloud-AB.git
*-FIC- (see above) SET CLASSLIB TO (Addbs(JustPath(Sys(16))) + '..\CLASSE\EASY.VCX') ADDITIVE && easy.vcx derives from aw.vcx
&& Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
&& /!\ make sure all SET PATH/LIBRary/CLASslib/PROCedure
&& executed after this line have the ADDITIVE clause
*-FIC- (see above) PUBLIC M.VERSAOEL, M.VERMAJOR AS Character, M.VERMINOR AS Character, M.VERREV AS Character && Variaveis que informam qual é a versao do sistema
M.VERSAOEL = ""
M.VERMAJOR = ""
M.VERMINOR = ""
M.VERREV = ""
*CLOSE DATABASES ALL
*SET SYSMENU OFF
SET NOTIFY CURSOR OFF
SET NOTIFY OFF
SET STATUS OFF
SET DATE BRITISH
SET CONSOLE OFF
SET CONFIRM ON
SET SAFETY OFF
SET BELL OFF
SET REPORTBEHAVIOR 80
SET MESSAGE TO ""
SET TALK OFF
SET NULL OFF
SET NULLDISPLAY TO ""
SET ESCAPE OFF
SET TABLEPROMPT OFF
*-FIC- (see above) SET PROCEDURE TO PRG\FUNCAO.PRG, PRG\REGISTRY.PRG, PRG\ZIP.PRG , PRG\VFPTRANSLATOR.PRG, PRG\ACESSOFTP.PRG, PRG\FTP.PRG, PRG\FOXBARCODE.PRG, PRG\GPIMAGE2.PRG, PRG\MENUNEW.PRG
*-FIC- (see above) SET CLASSLIB TO classe\ambiente, classe\dados, classe\padrao, classe\lanca ,classe\laudo, classe\termo, classe\barra ,classe\menu, classe\vfp-skin2 ADDITIVE
*-FIC- (see above) SET CLASSLIB TO classe\_base, classe\treeview, classe\foxcharts, classe\gdiplusx, classe\rtfbar, classe\txtextcontrol19, classe\themedtitlebar, classe\themedtitlebarbase ADDITIVE
*-FIC- (see above) SET CLASSLIB TO classe\_ws3client.vcx, classe\sfmenu.vcx, classe\_controls.vcx, classe\_webview.vcx ADDITIVE
*!* IF SYSMETRIC(1) = 800
*!* _screen.picture = 'FundoEasylab800.jpg'
*!* ELSE
*!* IF SYSMETRIC(1) = 1024
*!* _screen.picture = 'FundoEasylab1024.jpg'
*!* ELSE
*!* _screen.picture = 'FundoEasylab.jpg'
*!* ENDIF
*!* ENDIF
IF this.wlWeb = .F.
DO CASE
CASE SYSMETRIC(1) = 1024
_screen.picture = "C:\SE\EASYLABFOXPRO\FIGURA\LAB1024.JPG"
CASE SYSMETRIC(1) = 1280
_screen.picture = "C:\SE\EASYLABFOXPRO\FIGURA\LAB1280.JPG"
CASE SYSMETRIC(1) = 1366
_screen.picture = "C:\SE\EASYLABFOXPRO\FIGURA\LAB1366.JPG"
CASE SYSMETRIC(1) = 1440
_screen.picture = "C:\SE\EASYLABFOXPRO\FIGURA\LAB1440.JPG"
CASE SYSMETRIC(1) = 1920 OR SYSMETRIC(1) = 1536
_screen.picture = "C:\SE\EASYLABFOXPRO\FIGURA\LAB1920.JPG"
OTHERWISE
_screen.picture = "C:\SE\EASYLABFOXPRO\FIGURA\LAB1024.JPG"
ENDCASE
_screen.icon = "c:\se\easylabfoxpro\figura\easylabnew.ico"
_screen.Closable = .T.
ENDIF
_screen.AddObject("metodo_pad","metodo_pad")
*-FIC- (see above) PUBLIC M.VISUEMTELA AS Boolean && Variavel para ser usada pela visualizacao do mapa de trabalho
M.VISUEMTELA = .F.
*-FIC- (see above) PUBLIC oPARAM && Objeto com as configuracoes gerais do sistema
*-FIC- (see above) PUBLIC _prot && Objeto de protecao do sistema
*-FIC- (see above) PUBLIC oMENS && Objeto para exibir corretamente a barra de informacoes no rodapé do sistema
*-FIC- (see above) PUBLIC M.VERSAOEL && Variavel que informa qual é a versao do sistema
*-FIC- (see above) PUBLIC M.DATLICATU && Data atual em que a licença do sistema se expira
*-FIC- (see above) PUBLIC M.oFOXBARCODE
M.oFOXBARCODE = CREATEOBJECT("FoxBarcode")
*-FIC- (see above) PUBLIC oMENU && Objeto com as propiedades do menu
*-FIC- (see above) PUBLIC M.FIGLAUDO
M.FIGLAUDO = 0
*SET STEP ON
IF !FILE("FoxTools.fll")
*-FIC- Replaced by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
*-FIC- MESSAGEBOX("Para o número da versão ficar disponivel no sistema é necessario o arquivo FOXTOOLS.FLL estar na pasta do
*-FIC- sistema, baixe o mesmo no link http://www.softeasy.com.br/UTILS/foxtools.fll ou por favor entrar em contato com o
*-FIC- suporte técnico.",48,"Atenção")
*-FIC- (In web mode, no user can attend modal state at app startup, please condition with [if this.wlLAN]) wMessageBox("Para o número da versão ficar disponivel no sistema é necessario o arquivo FOXTOOLS.FLL estar na pasta do sistema, baixe o mesmo no link http://www.softeasy.com.br/UTILS/foxtools.fll ou por favor entrar em contato com o suporte técnico.",48,"Atenção")
ELSE
*** Informações sobre o Sistema ***
*-FIC- (see above) set library to FoxTools additive
IF this.wlWeb = .F.
dimension vSW_Info(12)
GetFileVersion( sys(16,0), @vSW_Info )
*!* vSW_Info(1) && 1 Comentários / Comments
*!* vSW_Info(2) && 2 Nome da empresa / Company Name
*!* vSW_Info(3) && 3 Descrição do arquivo / File Description
*!* vSW_Info(4) && 4 Versão do arquivo / File Version
*!* vSW_Info(5) && 5 Nome interno / Internal Name
*!* vSW_Info(6) && 6 Direitos Legais de Copyright / Legal Copyright
*!* vSW_Info(7) && 7 Marcas Legais registradas / Legal Trademarks
*!* vSW_Info(8) && 8 Nome original do arquivo / Original File Name
*!* vSW_Info(9) && 9 Construção privada / Private Build
*!* vSW_Info(10) && 10 Nome do produto / Product Name
*!* vSW_Info(11) && 11 Versão do produto / Product Version
*!* vSW_Info(12) && 12 Construção especial / Special Build
M.VERSAOEL = vSW_Info(4)
M.VERMAJOR = ALLTRIM(GETWORDNUM(M.VERSAOEL, 1, "."))
M.VERMINOR = ALLTRIM(GETWORDNUM(M.VERSAOEL, 2, "."))
M.VERREV = ALLTRIM(GETWORDNUM(M.VERSAOEL, 3, "."))
ENDIF
ENDIF
*-FIC- (see above) LOCAL M.TITPROG as String, M.IDPARAM AS Integer
TRY
M.TITPROG = "Easylab Sistema de Gestão Laboratorial Versão " + M.VERSAOEL + " - Softeasy Tecnologia "
CATCH
M.VERSAOEL = "99.99.99"
M.TITPROG = "Easylab Sistema de Gestão Laboratorial Versão " + M.VERSAOEL + " - Softeasy Tecnologia "
ENDTRY
IF this.wlWeb = .F.
IF IsAppRunning(M.TITPROG)
QUIT
ENDIF
IF VAL(STR(VAL(STRTRAN(VERSION(4),".","")),15)) < 90000007423
*-FIC- Replaced by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
*-FIC- MESSAGEBOX("Para o funcionamento correto do sistema é necessario a atualização das dlls do mesmo, favor entrar em
*-FIC- contato com o suporte técnico",48,"Atenção")
*-FIC- (In web mode, no user can attend modal state at app startup, please condition with [if this.wlLAN]) wMessageBox("Para o funcionamento correto do sistema é necessario a atualização das dlls do mesmo, favor entrar em contato com o suporte técnico",48,"Atenção")
*QUIT
ENDIF
IF !FILE("SYSTEM.APP")
*-FIC- Replaced by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
*-FIC- MESSAGEBOX("Para o funcionamento correto do sistema é necessario o arquivo SYSTEM.APP estar na pasta do sistema, favor
*-FIC- entrar em contato com o suporte técnico",48,"Atenção")
*-FIC- (In web mode, no user can attend modal state at app startup, please condition with [if this.wlLAN]) wMessageBox("Para o funcionamento correto do sistema é necessario o arquivo SYSTEM.APP estar na pasta do sistema, favor entrar em contato com o suporte técnico",48,"Atenção")
*QUIT
ENDIF
IF !FILE("richtx32.ocx")
*-FIC- Replaced by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
*-FIC- MESSAGEBOX("Para o funcionamento correto do sistema é necessario o arquivo RICHTX32.OCX estar na pasta do sistema,
*-FIC- favor entrar em contato com o suporte técnico",48,"Atenção")
*-FIC- (In web mode, no user can attend modal state at app startup, please condition with [if this.wlLAN]) wMessageBox("Para o funcionamento correto do sistema é necessario o arquivo RICHTX32.OCX estar na pasta do sistema, favor entrar em contato com o suporte técnico",48,"Atenção")
ENDIF
IF !FILE("TX4OLE19.OCX")
*-FIC- Replaced by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/01/2018 15:56
*-FIC- MESSAGEBOX("Para o funcionamento correto do sistema é necessario o arquivo TX4OLE19.OCX estar na pasta do sistema,
*-FIC- favor fazer o download no link www.softeasy.com.br/UTILS/comrtf19arqs.zip ou entrar em contato com o suporte
*-FIC- técnico",48,"Atenção")
*-FIC- (In web mode, no user can attend modal state at app startup, please condition with [if this.wlLAN]) wMessageBox("Para o funcionamento correto do sistema é necessario o arquivo TX4OLE19.OCX estar na pasta do sistema, favor fazer o download no link www.softeasy.com.br/UTILS/comrtf19arqs.zip ou entrar em contato com o suporte técnico",48,"Atenção")
ENDIF
_screen.Caption = M.TITPROG
_screen.Themes = .T.
_screen.WindowState = 2
ENDIF
ON SHUTDOWN sair()
ON ERROR DO CTRERRO With Upper(Message()), Program(), LTrim(Str(LineNo()))
*On Error Do TrataErro With Error( ), Message( ), Message(1), Program( ), Lineno( )
_screen.AddProperty("sist_apoio",0) && Informa se o sistema é o de apoio
_screen.AddProperty("opera",0) && Propriedade do operador logado no sistema
_screen.AddProperty("nomeopera","") && Propriedade com o nome operador logado no sistema
_screen.AddProperty("valorbusca",0) && Local para armazenar valores entre cadastros
_screen.AddProperty("valorbusca2",0) && Local para armazenar valores entre cadastros
_screen.AddProperty("handle",0) && Cria propriedade de conexao com o banco de dados
_screen.AddProperty("Confirma",0) && Confirma ou não a deleção do registro
_screen.AddProperty("Codigocaixa",0) && Codigo do caixa atual
_screen.AddProperty("Justificativa","") && Justificativa
_screen.AddProperty("tipobanco","")
_screen.AddProperty("internet",0)
_screen.AddProperty("captionform","") && Guarda caption do form
_screen.AddProperty("visivelmapa",.F.) && para botao sair mapa ficar visivel
_screen.AddProperty("demo",.F.)
_screen.AddProperty("gravapos",.F.)
_screen.AddProperty("gravaset",.F.)
_screen.AddProperty("gravagrade",.F.)
_screen.AddProperty("gravaposimp",.F.)
_screen.AddProperty("mapa_id",0)
_screen.AddProperty("exameanterior",0)
_screen.AddProperty("assope",0) && Propriedade do operador que assinou o exame
_screen.AddProperty("postopadrao","") && Guarda posto padrao para cadastro rapido
_screen.AddProperty("dataentregaf","") && Propriedade com o a frase FALTA MATERIAL - MEDRADIUS MACEIO
_screen.AddProperty("inter",.F.) && saber se esta no sistema interface
_screen.AddProperty("fila",.F.) && saber se esta no sistema fila
_screen.AddProperty("temvalesp",.F.) && saber se tem valor especial para copiar
_screen.AddProperty("tipografico",0) && Propriedade tipo de grafico para preencher combo
_screen.AddProperty("subtitulo","") && Propriedade sub titulo grafico
_screen.AddProperty("usagrafico",.F.) && Propriedade usa grafico laudo
_screen.AddProperty("temexadesc",.F.) && saber se tem exames descobertos para copiar
*_screen.AddProperty("etq",.F.)
_screen.AddProperty("liberacaopac",0) && Indica qual foi a liberacao no paciente 8-so o exame 9-todos exames 0-nenhum
_screen.AddProperty("lancou",0)
_screen.AddProperty("custopac",0)
_screen.AddProperty("altcustopac",.F.)
_screen.AddProperty("caminhotxt","") && caminho txt colocado para arquivo tipo mtx - Edgar - 06.06.2011
_screen.AddProperty("datlicatu","") && propriedade de data licença atual
_screen.AddProperty("cripto_pass",0)
_screen.AddProperty("cmdatu","")
_screen.AddProperty("ultimaacao",TIME()) && grava o hora da ultima acao do operador no sistema
_screen.AddProperty("ope_verificado",0)
_screen.AddProperty("posamopdf",IIF(VARTYPE(__posamopdf) = "C",__posamopdf,""))
_screen.AddProperty("isdll",.F.)
_screen.AddProperty("isapp",.F.)
_screen.AddProperty("visu_laudoimp",.F.)
_screen.AddProperty("fillibconv","")
_screen.AddProperty("fillibset",0)
_screen.AddProperty("fillibpos","")
_screen.AddProperty("filtdev",.F.)
_screen.AddProperty("pedcarteirinha",.F.) && pedir para ler carteirinha do usuario da unimed - usa validador para compor a trilha1 e trilha2
_screen.AddProperty("valcarteirinha","") && conteudo carteirinha do usuario da unimed - usa validador para compor a trilha1 e trilha2
_screen.AddProperty("validadorindcli","") && indicação clinica para gerar no validador online
_screen.AddProperty("laudoweb",.F.)
_screen.AddProperty("idfila",0) && guardar id fila para atualizar o movpac_id
_screen.AddProperty("senha_certificado_rt_atu","")
_screen.AddProperty("restelalib",0)
_screen.AddProperty("dthorachecon",CTOT(""))
_screen.AddProperty("rascunho_lau",0)
_screen.AddProperty("medicorea_id",0)
_screen.AddProperty("nome_medrea","")
_screen.AddProperty("crm_medrea","")
_screen.AddProperty("prontu_id",0)
_screen.AddProperty("alteraplano",.F.)
_screen.AddProperty("incluiureg",0)
_screen.AddProperty("regidatu",NULL)
_screen.AddProperty("dominio",NULL)
_screen.AddProperty("cmdatu_dominio","")
_screen.AddProperty("handle_dominio",0)
_screen.AddProperty("id_dominio",0)
_screen.AddProperty("ihandle",0)
_screen.AddProperty("debug_web",.F.)
_screen.AddProperty("atendinclusoag",.F.)
_screen.AddProperty("movpac_id_atendinclusoag",0)
return m.success && application won't start if .F.
endproc
* ---------------------
PROCEDURE Destroy
* add here [or move from this.init()]
* the instructions you need to execute when application unloads,
* such as garbage collection and/or RemoveProperty(_Screen, ...)
return DoDefault()
* You don't need to restore Set("Path"), Set("Procedure") and Set("Classlib")
* as DoDefault() does this automatically.
endproc
* =====================================================
ENDDEFINE && CLASS easySets && Added by FoxInCloud Adaptation Assistant version 2.26 (source mode) on 06/03/2018 10:40
* =====================================================
&& This is a sample program for SETting application's environment
&& Ideally your application's LAN (desktop) and WEB versions SHARE this module
&& You may use either of these three implementations (see properties in easyServer.prg):
&& Implementation .cAppSetsLib .cAppSets .lAppSetsClass
&& --------------------- ------------- ---------- ---------------
&& 1-Instantiate 'easySets' 'easySets.prg' 'easySets' .T.
&& 2-Execute this program 'easySets.prg' '' .F.
&& 3-Execute 'easySets' proc 'easySets.prg' 'easySets' .F.
&& Notes:
&& - In Web mode, as usually in LAN/desktop mode, when this module executes,
&& Curdir() is main program's folder where the project sits: '..\' in this case
&& - As FoxInCloud executes application in a Session class,
&& dataSession-dependant SETtings don't need be restored
#IF .F. && move or delete this line if you intend to adapt this code &&
&& SAMPLE IMPLEMENTATION # 1 (RECOMMENDED): instantiate an 'easySets' class
* ===================================================
&& In this implementation this.Destroy() restores initial environment (useful during development)
* ===================================================
DEFINE CLASS easySets as awSets of awPublic.prg
* ---------------------
PROCEDURE Init
lparameters ;
result; && @ result of application startup - appears in .../foxincloud-status.easy
, toAppHost as awAppHost of awAppHost.fxp && Web Application Host object
* m.toAppHost provides access to:
* - any PROTECTED property added to your server class > modify command easyServer.prg - class easyServer
* - your application's configuration object in m.toAppHost.oConfigApp > modify command easyServer.prg - class easyAppConfig
* - many other properties and methods that you can discover by setting a break point and typing 'm.toAppHost.' to trigger intellisense
* HINT
* Your code can take advantage of the following properties and methods:
#if .F.
this.wlWeb && = !this.wlLAN && application runs in Web mode
this.wlLAN && = !this.wlWeb && application runs in LAN (desktop) mode
this.lDevMode && application runs in development mode
this.Set(<setting>, <value> [, 1,2,...]) && performs a SET and restores with this.destroy() - see abDev.prg!abSet
#endIf
local success as Boolean
success = DoDefault(@m.result) && sets this.wlWeb, this.wlLAN, this.lDevMode, this.oConfigApp (from easyTest|Prod.ini)
if m.success
&& at this point, curdir() is folder where main program sits, you can easily add child folders to set('path')
SET PATH TO 'progs,forms,reports,images,data' ADDITIVE && ADDITIVE don't forget!
if !this.lAutomation && in automation mode, VFP automatically SETs PROCEDURE and CLASSLIB to any file included - reSETting to these files can cause a runtime error
SET PROCEDURE TO myStuff1, myStuff2 ADDITIVE && ADDITIVE don't forget!
SET CLASSLIB TO myClasses ADDITIVE && ADDITIVE don't forget!
endIf
SET DELETED OFF
SET SAFETY OFF
SET DATE AMERICAN
if m.this.wlLAN
SET TALK OFF
endIf
OPEN DATABASE myDatabase
wMenu('set sysmenu to') && remove system menu
do myMenu.mpr && installs application's menu
endif
* FoxInCloud Application Server instantiates forms dynamically, you should not execute any form here
* In Web mode, easyProcess.Index (modify command easyServer) executes your startup form (eg login or splash)
* In LAN mode, your startup program should display the initial form after this has completed
* If anything serious happens during class initialization, set:
* success = .F.
* result = [the reason(s) why environment could not be set and/or application should not start]
* in Web mode, this error will get written into the application log, and a mail sent to administrator.
* in LAN mode, you could do something similar
return m.success
endProc
* ---------------------
PROCEDURE Destroy
* here, restore environment items that are not handled automatically
endProc
* ---------------------
hidden procedure Init_dataSession_for_child_forms_launched_at_startup
lparameters ;
result as String; && @ error if any
, toAppHost as awAppHost of awAppHost.fxp; && Application Host object
* sample method
* for child forms launched at server startup, use the aliases they would normally find in a parent form dataSession
* ouvre les alias dont les écrans enfant lancés au démarrage ont besoin hors du contexte de leur écran parent
if Empty(m.toAppHost.uFormsLaunchAtStartup)
return
endIf
local success as Boolean
success = .T.
open database easy
if lInList('myForm1.scx', m.toAppHost.uFormsLaunchAtStartup)
success = this.use('view1;view2;table1,Alias1') and m.success
endIf
if lInList('myForm2.scx', m.toAppHost.uFormsLaunchAtStartup)
success = this.use('view2;view3;table2') and m.success
endIf
return m.success
endProc
* ---------------------
hidden procedure use
lparameters ;
result as String; && @ error if any
, aliases; && Aliases to use
* sample method
* uses a list of tables and/or views
* ouvre une liste de tables et/ou de vues
local success as Boolean;
, aView[1] as String;
, nView as Integer;
, aTable[1] as String;
, cTable as String;
, cAlias as String;
, cNoData as String;
, oException as Exception;
nView = ADBObjects(aView, "VIEW")
success = .T.
if ALines(m.aTable, m.aliases, 5, ';') > 0
for each cTable in m.aTable
try
cAlias = Evl(GetWordNum(m.cTable, 2, ','), JustStem(m.cTable))
cTable = JustStem(GetWordNum(m.cTable, 1, ','))
if !Used(m.cAlias)
cNoData = Iif(Ascan(m.aView, m.cTable, 1, -1, 1, 7) > 0, 'NODATA', '')
use (m.cTable) alias (m.cAlias) in 0 again shared &cNoData
endIf
do case
case Lower(m.cTable) == Lower('countryCodes')
&& this view requires data loaded; eg view on a referential table such as country codes ...
local parm1, parm2
parm1 = someValue
parm2 = otherValue
Requery(m.cAlias)
endCase
catch to oException
success = cResultAdd(@m.result, cException(m.oException)) && cResultAdd(), cException(): modify command abDev
endtry
endFor
endIf
return m.success
endProc
ENDDEFINE && CLASS easySets
&& SAMPLE IMPLEMENTATION # 2: execute 'easySets.prg'
* ---------------------------------------------------
SET PATH TO 'progs,forms,reports,images,data' ADDITIVE && ADDITIVE don't forget!
if !wlAutomation()
SET PROCEDURE TO myStuff1, myStuff2 ADDITIVE && ADDITIVE don't forget!
SET CLASSLIB TO myClasses ADDITIVE && ADDITIVE don't forget!
endIf
SET DELETED OFF
SET SAFETY OFF
SET DATE AMERICAN
OPEN DATABASE myDatabase
&& ...
&& SAMPLE IMPLEMENTATION # 3: execute 'easySets' procedure
* ---------------------------------------------------
PROCEDURE easySets
SET PATH TO 'progs,forms,reports,images,data' ADDITIVE && ADDITIVE don't forget!
if !wlAutomation()
SET PROCEDURE TO myStuff1, myStuff2 ADDITIVE && ADDITIVE don't forget!
SET CLASSLIB TO myClasses ADDITIVE && ADDITIVE don't forget!
endIf
SET DELETED OFF
SET SAFETY OFF
SET DATE AMERICAN
OPEN DATABASE myDatabase
&& ...
endProc
#endIf && move this if you intend to adapt this code &&
procedure xxxSets.Init()
_screen.AddProperty("handle", sqlstringconnect(…)) && not 0
define class xxxServer as awServer
…
_ScreenPropertiesSaveNot = 'handle, …'
It seems that the error is related to the time to update the environment and the connection between users, due to the value of handle being different between them because they are different databases. I includes a "While" in the command that generates the sequential and apparently solved the problem.
LPARAMETERS __opc && 1 para incluir e 2 para atualizar
WITH thisform
LOCAL M.ID AS Integer
IF __opc = 1
SELECT CRCAIXA1
APPEND BLANK IN CRCAIXA1
M.ID = 0
DO WHILE M.ID = 0 && While Included
M.ID = CAST(.metodo_pad.gera_id("caixa1_id_seq") AS I)
ENDDO
ELSE
M.ID = CRCAIXA1.ID
ENDIF
REPLACE ;
DESCRICAO WITH .descricao_caixa1,;
DESCTIPFOR WITH .desctipfor_caixa1,;
TIPFOR WITH .tipfor_caixa1,;
VALFOR WITH NUM_STR(thisform.textbox_padrao5.Value,10,2,"N"),;
OBSCAI WITH thisform.textbox_padrao3.Value, ;
FORPAG_ID WITH .forpag_id_caixa1,;
ID WITH M.ID ;
IN CRCAIXA1
ENDWITH
Hi Arcadio
I have made the same thing in my code.. Insert a SqlStringConnect() in a do while enddo..
iDebut = SECONDS()
DO WHILE .T.
DOEVENTS
_SCREEN._gnconnect = SQLSTRINGCONNECT(m.cChaineConnexion, .T.)
IF NVL(_SCREEN._gnconnect, 0) > 0
=SQLSETPROP(_SCREEN._gnconnect,"ConnectTimeOut",30) && timeout 30 secondes
* Connexion réussie
=STRTOFILE(TTOC(DATETIME()) + ': ' + ALLTRIM(STR(_VFP.PROCESSID)) + '-->' + 'Connexion N°' + ALLTRIM(STR(_SCREEN._gnconnect)) + CHR(13) + CHR(10), _SCREEN._locale + '_postgresql.log', 1)
lReturn = .T.
EXIT
ENDIF
IF SECONDS() > m.iDebut + 30
* Echec connexion
EXIT
ENDIF
=Sleep(150)
ENDDO
Regards Gilles
OK, I now understand that each user (I guess based on the company he/she belongs to/works for) needs a specific database handle.
As we have no experience with such an architecture I would rather install one site and one application per client company: company1.easysoft.com
, company2.easysoft.com
, etc., each in a separate folder with a separate EXE; it'd require that you either have one project per company (just for generating specific COM object GUID) or manipulate _VFP.activeProject.GUID
programmatically when generating the web EXEs per company.
However, your system should theoretically work fine, for the reasons hereafter.
FoxInCloud restores the application environment, including _Screen.properties
, as a VERY FIRST STEP before doing anything on the application; you can see it on the FoxInCloud Web App Dashboard such as this one, column restoring app. state for user
.
So, if your server saves _Screen.handle
(thus not add handle
it to xxxServer._ScreenPropertiesSaveNot
as I wrote earlier, before having the full picture), FoxInCloud restores it before querying any view or CAD, and it should always be so.
Of course, as the user can call any master form in any order (using an URL in history), he/she can query a form while having _screen.handle = 0
and get into trouble. To overcome this, you NEED to check that ONLY THE LOGIN FORM (setting _screen.handle
for the user) has .wlAnonymousAllowed = .T.
.
That's all I can tell for now…
Update: a side benefit of having one site and app per company is that it makes it easier to upgrade a company on another server when traffic increases. By merging all companies into a single application you may get into troubles at some point down the road.
Hi Thierry,
I understood what you said. I will think here. However, I don't think I should be no "handle" errors just because of the fact that there are quick actions between different user sessions. As for my idea of several customers using the same installation, this would not be mandatory, it would be just another way of using our app. We are considering all possible scenarios and the scenario of several customers in a single installation would be more possible for smaller customers.
quick actions between different user sessions
whether user actions are quick or slow makes NO difference at all.
User status, including app environment:
- is saved after EACH user action
- is restored before executing user action whenever the current user is different from the previous user on the current server.
Please keep in mind that, in production, you'll run several logical servers (COM/EXE) on the same machine (WC supports up to 32). So users will switch between logical servers.
Arcadio
In this case, what are the reasons why the users of the different client companies would not use the same database with the same PostGresQL handle? This is what I do, I just add in each table a column to identify the company of the connected customer and all my views or SQLEXE commands () use this column to filter the records accessible by the user. This requires, of course, that the data structure of the database is the same for all tables and for all client companies.
Gilles
Hello Giles,
We would have to totally rewrite our software for that. My idea is good as long as it works, since the customer's postrgresql database could in theory be anywhere.
For some reason, if access quickly enters the sessions, the _screen.tipobanco property is going blank and that is the reason for the problem. However, I did not identify the cause of this. It is reported correctly in xxxsets.ini. Follow below the link video with the problem.
&& gera_id method.
LPARAMETERS __NOMESEQ
DO CASE
USE IN SELECT("MAXIMO")
CASE ALLTRIM(_screen.tipobanco) = "POSTGRESQL" OR ALLTRIM(_screen.tipobanco) = "CACHE"
LOCAL M.INSTRUCAOSQL AS String
TEXT TO M.INSTRUCAOSQL NOSHOW
SELECT CAST(NEXTVAL(?__NOMESEQ) AS CHAR(13)) AS NEXTVAL
ENDTEXT
IF SQLEXEC(_screen.handle,M.INSTRUCAOSQL,[MAXIMO]) > 0
*SELECT maximo
*COPY TO C:\seazure\easylabwebfoxpro\maximo
STRTOFILE(CAST(_screen.dominio as m),"C:\seazure\easylabwebfoxpro\a.txt")
RETURN CAST(MAXIMO.NEXTVAL as i)
ELSE
STRTOFILE(CAST(_screen.dominio as m),"C:\seazure\easylabwebfoxpro\b.txt")
RETURN 0
ENDIF
CASE ALLTRIM(_screen.tipobanco) = "SQL SERVER"
LOCAL M.INSTRUCAOSQL AS String
TEXT TO M.INSTRUCAOSQL NOSHOW
SELECT SEQ + 1 AS SEQ FROM SEQUENCIA TABLOCK WHERE TABELA = ?__NOMESEQ
ENDTEXT
M.FEZ = SQLEXEC(_screen.handle,M.INSTRUCAOSQL,[MAXIMO])
M.FEZ = SQLEXEC(_screen.handle,[UPDATE SEQUENCIA SET SEQ = ?MAXIMO.SEQ WHERE TABELA = ?__NOMESEQ])
STRTOFILE(CAST(_screen.dominio as m),"C:\seazure\easylabwebfoxpro\c.txt")
RETURN MAXIMO.SEQ
ENDCASE
STRTOFILE(CAST(_screen.dominio as m),"C:\seazure\easylabwebfoxpro\d.txt")
STRTOFILE(CAST(__NOMESEQ as m),"C:\seazure\easylabwebfoxpro\e.txt")
STRTOFILE(CAST(_screen.tipobanco as m),"C:\seazure\easylabwebfoxpro\e.txt")
Hi Arcadio,
For STRTOFILE()
, you should have a different file for each screen, right ?
I used the strtofile to debug, as it is a difficult problem to find. The right thing would be to generate only A.txt and never d.txt and e.txt. Something is erasing the _screen.tipobanco property
It is reported correctly in xxxsets.ini
do you mean xxxSets.init()
?
I see no reason why the problem would occur in COM mode and not in IDE mode.
As you know the reason for the problem (empty(_Screen.tipobanco)
), you can:
0- to be sure your *.fxp
are in sync, do atPJcompile
1- set a breakpoint on this condition (ctrl+B
opens the form) :
2- disable the breakpoint, close the debugger and start the server:
3- when your test case is ready (both browsers on the test user and the test form), re-enable the breakpoint and open the debugger:
The program will stop on the instruction that blanks _Screen.tipoBanco
.
Just a guess, I suspect an *_assign()
method that is not adapted.
Hi Arcadio It is possible that the connection to the database server is busy and that the SQLEXEC () command is not executed by the database. Before launching an SQLEXEC () command, I test the status of the database engine with the BUSY function (at least for PostGresql):
FUNCTION SqlPasBloque AS Boolean
LOCAL lretour AS Boolean , iDebut AS INTEGER , iTimeOut AS INTEGER
=open_dbc()
iTimeOut = 30
iDebut = SECONDS()
DO WHILE .T.
DOEVENTS
IF NOT SQLGETPROP(_SCREEN._gnconnect, 'ConnectBusy')
lretour = .T.
EXIT
ENDIF
IF SECONDS() > m.iDebut + m.iTimeOut
lretour = .F.
EXIT
ENDIF
=Sleep(150)
ENDDO
* WAIT CLEAR
RETURN m.lretour
ENDFUNC
IF SqlPasBloque()
= SQLEXEC(_SCREEN._gnconnect, m.p_Action, m.p_curseur)
ENDIF
regards Gilles
Perfect Gilles,
I will implement this in my system, Thanks. However the biggest problem is to lose the value contained in the property. Thierry will help me find this out in a private consultation.
Hi Arcadio,
Regarding the ability to switch connection across users, as you use CursorAdapters
, you can change .dataSource
at run time.
If you really need to do that, I have several possible solutions to be discussed in private support.
The multiple datasource is even working the way I showed in the topic, https://support.west-wind.com/Thread5GN1DN3X5.wwt, I don't know if it's the best way, but it's working. Just informing the datasource in init simply, it didn't work. Perhaps it is related to the same problem as the property "_screen.tipobanco"
Hi Arcadio,
This multi-database handles scenario is quite touchy and I suggest you run full tests (combining all scenarios) before putting it in production.
To make it work you need to swap cursorAdapter.DataSource
for each user and one simple way to do that is to make sure that your cursorAdapters are members of form.dataEnvironment
and add ”dataSource”
to cursorAdapter.wcPropSave
.
But again, as we have never experienced such a scenario, it requires heavy testing.
Also, You need to consider the many-to-many relation between servers and users; if a user gets a handle on one server, you’ll need to somehow get him another handle on another server.
To overcome this, I would create a pool of connections with a table between companies, users and handles; upon each request, I would set _screen.handle
to what is appropriate to the user and set CAD.dataSource
to _screen.handle
in CAD.dataSource_assign()
, thus ignoring what was saved.
Update: forgot about the 2019 thread you mention. All this is confusing. Please take some time to clearly state your issues. Thanks.