Microsoft KB Archive/270106

= PRB: VFP ODBC Driver in COM DLL Under MTS Package May Hang =

Article ID: 270106

Article Last Modified on 10/15/2003

-

APPLIES TO


 * Microsoft Visual FoxPro 5.0 Standard Edition
 * Microsoft Visual FoxPro 6.0 Professional Edition

-



This article was previously published under Q270106



SYMPTOMS
A client application calls a FoxPro Component Object Model (COM) .dll file in an Microsoft Transaction Server (MTS)/COM+ package. Under certain circumstances, the client application may hang. This behavior can occur when:
 * The COM DLL accesses a FoxPro datasource through ODBC.
 * The Fetch Data In Background option is set to YES for the ODBC connection that is used by the .dll server.



RESOLUTION
To work around this problem, deselect the Fetch Data in Background option on the DSN, either visually or through code.



Steps to Reproduce Behavior
Create the COM Server:  Copy the TESTDATA database to the computer that is running MTS/COM+. Create a new project in Microsoft Visual FoxPro called VFP_PROB .  Save the following code to a new program and add it to the project. (Remember to change the DATA_PATH constant to a valid path. It needs to point to a local directory on your MTS/COM+ computer.) *********** START SERVER CODE ************** DEFINE CLASS SERVER AS CUSTOM OLEPUBLIC PROCEDURE GETDATA(lcSQLCmd, lcFetchOn) LOCAL lcDSN, lnSQLHand, lnSQLSuccess, lcFDIB, ; lcRetVal,lnStartTime,lnEndTime,lcQueryDuration

*!* Change path appropriately for your computer. #DEFINE DATA_PATH &quot;C:\DATA\TESTDATA.DBC&quot; lcFDIB = IIF(lcFetchOn,&quot;YES&quot;,&quot;NO&quot;)

lcDSN = &quot;DRIVER=Microsoft Visual FoxPro Driver;&quot; + ; &quot;UID=;Deleted=Yes;Null=Yes;Collate=Machine;BackgroundFetch=&quot; + lcFDIB + &quot;;&quot; + ; &quot;Exclusive=No;SourceType=DBC;SourceDB=&quot; + DATA_PATH + &quot;;&quot;

lnSQLHand = SQLSTRINGCONNECT(lcDSN) IF lnSQLHand < 0 lcRetVal = THIS.RaiseError RETURN lcRetVal ENDIF

lnStartTime = DATETIME lnSQLSuccess = SQLEXEC(lnSQLHand,lcSQLCmd,&quot;ResultSet&quot;) lnEndTime = DATETIME lcQueryDuration = TRANSFORM(ROUND(lnEndTime - lnStartTime,0)) + &quot; seconds&quot; IF lnSQLSuccess < 0 lcRetVal = THIS.RaiseError RETURN lcRetVal ENDIF

lcRetVal = TRANSFORM(RECCOUNT(&quot;ResultSet&quot;)) + ; &quot; Records Returned In ~ &quot; + lcQueryDuration + ; &quot;. 'Fetch Data In Background' = &quot; + lcFDIB + &quot;.&quot; USE IN ResultSet SQLDISCONNECT(0) CLOSE DATABASES ALL RETURN lcRetVal ENDPROC

PROCEDURE RaiseError LOCAL laErrArray[1], lcErrMsg AERROR(laErrArray) lcErrMsg = laErrArray(3) SQLDISCONNECT(0) RETURN lcErrMsg ENDPROC

ENDDEFINE  Build the project into a multi-threaded COM server (.dll). With a text editor, open the .vbr file that was generated when you built the .dll file (it is in the same directory as the .dll). Make note of the CLSID because you need it later. Take the .dll and .tlb files to your computer running MTS/COM+. Add them to a package.For additional information on this process, click the article numbers below to view the articles in the Microsoft Knowledge Base:
 * END SERVER CODE ***********

191623 HOWTO: Distribute VFP COM Components used with MTS

223406 HOWTO: Create an Empty MTS Package to Add Components for ASP

</li></ol>

Create the Clients: <ol> Copy the following code to a program file in a new instance of Microsoft Visual FoxPro.</li> Change the COM_CLSID and COM_SERVER constants to the CLSID you made note of earlier, and also change the name of your MTS/COM+ computer.</li> Save the program as four different file names (1.prg, 2.prg, 3.prg, 4.prg, for example).</li>  Start three more instances of Microsoft Visual FoxPro, and then run the four separate programs, one in each instance. Eventually, all four instances of FoxPro stop processing queries. *********** START CLIENT CODE *********** LOCAL loVFPCOM, lnCaseNum, lcSQLCmd, lcExitKey, lcYear


 * 1) DEFINE FetchData  .T.
 * 2) DEFINE lnLower    1
 * 3) DEFINE lnUpper    5
 * 4) DEFINE COM_CLSID  &quot;{6F5C4280-C6B4-4D84-936D-57E4AFFB843F}&quot;
 * 5) DEFINE COM_SERVER &quot;\\MYSERVER&quot;

loVFPCOM = CREATEOBJECTEX(COM_CLSID,COM_SERVER)

DO WHILE .T.   lnCaseNum = INT((lnUpper - lnLower + 1) * RAND + lnLower) DO CASE CASE lnCaseNum = 1 lcYEAR = &quot;1992&quot; CASE lnCaseNum = 2 lcYEAR = &quot;1993&quot; CASE lnCaseNum = 3 lcYEAR = &quot;1994&quot; CASE lnCaseNum = 4 lcYEAR = &quot;1995&quot; CASE lnCaseNum = 5 lcYEAR = &quot;1996&quot; ENDCASE lcSQLCmd = &quot;SELECT * &quot; + ; &quot;FROM testdata!customer INNER JOIN testdata!orders &quot; + ; &quot;ON Customer.cust_id = Orders.cust_id &quot; + ; &quot;WHERE YEAR( Orders.order_date) = &quot; + lcYEAR

? &quot;Starting query...&quot; ? loVFPCOM.GETDATA(lcSQLCmd,FetchData) WAIT &quot;Requery in 3 seconds. Press 'q' to exit...&quot; TO lcExitKey TIMEOUT 3 ? &quot;&quot; IF lcExitKey = &quot;q&quot; EXIT ENDIF ENDDO RELE ALL To see this work, edit the four client programs and change the #DEFINE FetchData to .F. </li></ol>
 * END CLIENT CODE ***********

<div class="references_section">