COM+ object loses state, why?
-
Problem: I have a COM+ business logic object which seems to lose state for no aparent reason. But when I debug it in VB it works fine. ?!?!?! Baskground: My BL object has a method which returns a reference to itself. (Why? Short-story: I was returning an ADO Recordset, but then (for reasons beyond this article) I didn't want EOF to return True when the Recordset was at EOF.) So my BL object implements some of the ADO interface and passes calls to the underlying recordset which is now stored in a private variable; except the EOF property which does it's own thing. Gotcha: After calling the method from ASP/VBScript I get an object back alright, but the object has lost state. Here is sample code of the object being used: <% ... Dim oOrders, adorsOrders Set oOrders = Server.CreateObject("BusinessLogicLayer.OrderHistory") Set adorsOrders = oOrders.ListByPage(sCustomerID, lPageNo, lPageSize) Do Until adorsOrders.EOF ... Loop ... %> The line "Do Until..." biffs an error saying that the object was not set. At this point adorsOrders and oOrders are actually the same object because ListByPage returns Me. Furthur examination reveals that all of the object's internal variables have been initialized right after the method completes; even though the object shouldn't get garbaged till the bottom of the page. Now the oddest thing is that if I set a public string variable on object creation and then call a different method I can still access that variable and it contains "HelloWorld" as expected. But if I access it after calling this method which returns it's own reference then the string variable has now been reinitialised. Oh, did I mention that the object works fine if I debug it in VB? Any help leading to a fast solution out of this mess will earn you naming rights on my first born. ;p
-
Problem: I have a COM+ business logic object which seems to lose state for no aparent reason. But when I debug it in VB it works fine. ?!?!?! Baskground: My BL object has a method which returns a reference to itself. (Why? Short-story: I was returning an ADO Recordset, but then (for reasons beyond this article) I didn't want EOF to return True when the Recordset was at EOF.) So my BL object implements some of the ADO interface and passes calls to the underlying recordset which is now stored in a private variable; except the EOF property which does it's own thing. Gotcha: After calling the method from ASP/VBScript I get an object back alright, but the object has lost state. Here is sample code of the object being used: <% ... Dim oOrders, adorsOrders Set oOrders = Server.CreateObject("BusinessLogicLayer.OrderHistory") Set adorsOrders = oOrders.ListByPage(sCustomerID, lPageNo, lPageSize) Do Until adorsOrders.EOF ... Loop ... %> The line "Do Until..." biffs an error saying that the object was not set. At this point adorsOrders and oOrders are actually the same object because ListByPage returns Me. Furthur examination reveals that all of the object's internal variables have been initialized right after the method completes; even though the object shouldn't get garbaged till the bottom of the page. Now the oddest thing is that if I set a public string variable on object creation and then call a different method I can still access that variable and it contains "HelloWorld" as expected. But if I access it after calling this method which returns it's own reference then the string variable has now been reinitialised. Oh, did I mention that the object works fine if I debug it in VB? Any help leading to a fast solution out of this mess will earn you naming rights on my first born. ;p
-
show IDL and implementation of this metohd: oOrders.ListByPage(sCustomerID, lPageNo, lPageSize) soptest
HRESULT ListByPage( [in] BSTR sCustomerID, [in] long lPageNo, [in] long lPageSize, [out, retval] IDispatch** ); Public Function ListByPage(ByVal sCustomerID As String, _ ByVal lPageNo As Long, _ ByVal lPageSize As Long) As Object '================================================================================================== ' PURPOSE: Returns a page of orders. The page is specified by lPageNo and ' lPageSize. lTotalRecordCount returns the total number of records on all pages. ' ' Criteria field(s): ' sCustomerID ' lPageNo ' lPageSize ' lTotalRecordCount ' ' RETURNS: Disconnected recordset. '================================================================================================== On Error GoTo ErrorHandler Dim oOrderHistory As Object Dim vOrders As Variant Dim lTotalRecordCount As Long Set oOrderHistory = CtxCreateObject(m_RemoteOrderHistoryDALProgID, m_RemoteDALHost) vOrders = oOrderHistory.ListByPage(sCustomerID, lPageNo, lPageSize, lTotalRecordCount) Set oOrderHistory = Nothing Set m_adorsOrders = Variant2RecordSet(vOrders(1), vOrders(0)) m_lTotalRecordCount = lTotalRecordCount m_lLastRecordInCurrentRecordSet = (lPageNo - 1) * lPageSize + m_adorsOrders.RecordCount Set ListByPage = Me CtxSetComplete Exit Function ErrorHandler: Set oOrderHistory = Nothing CtxRaiseError m_strModuleName, "ListByPage" End Function
-
HRESULT ListByPage( [in] BSTR sCustomerID, [in] long lPageNo, [in] long lPageSize, [out, retval] IDispatch** ); Public Function ListByPage(ByVal sCustomerID As String, _ ByVal lPageNo As Long, _ ByVal lPageSize As Long) As Object '================================================================================================== ' PURPOSE: Returns a page of orders. The page is specified by lPageNo and ' lPageSize. lTotalRecordCount returns the total number of records on all pages. ' ' Criteria field(s): ' sCustomerID ' lPageNo ' lPageSize ' lTotalRecordCount ' ' RETURNS: Disconnected recordset. '================================================================================================== On Error GoTo ErrorHandler Dim oOrderHistory As Object Dim vOrders As Variant Dim lTotalRecordCount As Long Set oOrderHistory = CtxCreateObject(m_RemoteOrderHistoryDALProgID, m_RemoteDALHost) vOrders = oOrderHistory.ListByPage(sCustomerID, lPageNo, lPageSize, lTotalRecordCount) Set oOrderHistory = Nothing Set m_adorsOrders = Variant2RecordSet(vOrders(1), vOrders(0)) m_lTotalRecordCount = lTotalRecordCount m_lLastRecordInCurrentRecordSet = (lPageNo - 1) * lPageSize + m_adorsOrders.RecordCount Set ListByPage = Me CtxSetComplete Exit Function ErrorHandler: Set oOrderHistory = Nothing CtxRaiseError m_strModuleName, "ListByPage" End Function
-
Public Property Get EOF() As Boolean On Error GoTo ErrorHandler If m_lLastRecordInCurrentRecordSet >= m_lTotalRecordCount Then ' At this next line I get the error "Object variable or With block variable not set" EOF = m_adorsOrders.EOF Else EOF = False End If Exit Property ErrorHandler: CtxRaiseError m_strModuleName, "EOF" End Property
-
HRESULT ListByPage( [in] BSTR sCustomerID, [in] long lPageNo, [in] long lPageSize, [out, retval] IDispatch** ); Public Function ListByPage(ByVal sCustomerID As String, _ ByVal lPageNo As Long, _ ByVal lPageSize As Long) As Object '================================================================================================== ' PURPOSE: Returns a page of orders. The page is specified by lPageNo and ' lPageSize. lTotalRecordCount returns the total number of records on all pages. ' ' Criteria field(s): ' sCustomerID ' lPageNo ' lPageSize ' lTotalRecordCount ' ' RETURNS: Disconnected recordset. '================================================================================================== On Error GoTo ErrorHandler Dim oOrderHistory As Object Dim vOrders As Variant Dim lTotalRecordCount As Long Set oOrderHistory = CtxCreateObject(m_RemoteOrderHistoryDALProgID, m_RemoteDALHost) vOrders = oOrderHistory.ListByPage(sCustomerID, lPageNo, lPageSize, lTotalRecordCount) Set oOrderHistory = Nothing Set m_adorsOrders = Variant2RecordSet(vOrders(1), vOrders(0)) m_lTotalRecordCount = lTotalRecordCount m_lLastRecordInCurrentRecordSet = (lPageNo - 1) * lPageSize + m_adorsOrders.RecordCount Set ListByPage = Me CtxSetComplete Exit Function ErrorHandler: Set oOrderHistory = Nothing CtxRaiseError m_strModuleName, "ListByPage" End Function
JBoy wrote: CtxSetComplete Exit Function Heya, since you call CtxSetComplete (which I think makes a call to the SetComplete method of IObjectContext) you tell COM to make this object available for use by someone else as soon as the function ends, and COM then deactivates it and clears all class global parameters. Cheers /WW
-
JBoy wrote: CtxSetComplete Exit Function Heya, since you call CtxSetComplete (which I think makes a call to the SetComplete method of IObjectContext) you tell COM to make this object available for use by someone else as soon as the function ends, and COM then deactivates it and clears all class global parameters. Cheers /WW
-
Duh! Thank you thank you thank you... I drove myself nuts on that one. How did I miss that one myself?
Hehe, no probs...been there too (several times)! /WW