Microsoft KB Archive/120206

{|
 * width="100%"|

FIX: Incorrect Return Value From CRecordset::IsOpen

 * }

Q120206

-

The information in this article applies to:


 * The Microsoft Foundation Classes (MFC), included with:
 * Microsoft Visual C++, versions 1.5, 1.51, 1.52, 1.52b

-

SYMPTOMS
When CRecordset::IsOpen is called, it returns TRUE even if the CRecordset has not been opened.

This happens only if a CRecordset is constructed with a CDatabase pointer being passed to it.

CAUSE
CRecordset::IsOpen checks whether the statement handle of the recordset has been allocated as follows:

_AFXDBCORE_INLINE BOOL CRecordset::IsOpen const { ASSERT_VALID(this); return m_hstmt != SQL_NULL_HSTMT; } The statement handle is usually allocated when CRecordset::Open is called (that is, when a recordset is opened).

But, if a CRecordset is constructed with a CDatabase pointer being passed to it, the CRecordset constructor allocates a statement handle and assigns a value to the member variable m_hstmt. So, if a call to CRecordset::IsOpen is made after creating a CRecordset in this fashion, it returns TRUE even if the recordset is not open.

RESOLUTION
To work around this problem, use one of the following methods:

Create a Custom IsOpen Routine

 * 1) Because IsOpen is not a virtual function, create another function, such as "IsMyOpen", and call IsMyOpen instead of IsOpen.
 * 2) In your custom IsMyOpen, call the ODBC API function SQLNumResultCols to check whether the recordset has been opened. SQLNumResultCols returns the number of columns in the result set. If the function does not return an error message and the number of columns is not 0, then the recordset has been opened. The sample code for such a IsMyOpen function is given in the "MORE INFORMATION" section, below.

Use a Flag to Track Whether the Recordset Has Been Opened
Derive a class from CRecordset and create a new member variable that would be set whether the recordset has been opened. Override CRecordset::Open and set the flag in the function. Create a CRecordset::IsMyOpen that would check whether the flag is set. Then call IsMyOpen instead of IsOpen to check whether the recordset has been opened.

STATUS
Microsoft has confirmed this to be a bug in the products listed at the beginning of this article. This bug was corrected in the 32-bit version of MFC.

Sample Code
  BOOL CMyRecordset::IsMyOpen const {     if (m_hstmt == NULL) return FALSE; RETCODE nRetCode; SWORD nCols; AFX_SQL_SYNC(::SQLNumResultCols(m_hstmt, &nCols)); if (nRetCode == SQL_ERROR) {        TRACE0("Error: SQLNumResultCols failed during IsOpen.\n"); return FALSE; }     else if (nCols == 0) return FALSE; return TRUE; } Additional query words: 1.50 1.51 1.52 2.50 2.51 2.52 2.53

Keywords : kb16bitonly kbDatabase kbMFC kbODBC kbVC

Issue type :

Technology : kbAudDeveloper kbMFC