⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 axrecordset.cpp

📁 一个非常好用的ADO封装类,程序员不再需要跟烦人的COM接口打交道,写数据库程序不再麻烦!
💻 CPP
📖 第 1 页 / 共 4 页
字号:
#include "StdAfx.h"
#include "AxLib.h"

using namespace dbAx;

///////////////////////////////////////////////////////////////
//	Construction

CAxRecordset::CAxRecordset()
{
  m_pConnection = NULL;
  m_pCommand = NULL;
  m_piConnection = NULL;
  m_piRecordset = NULL;
  m_pFields= NULL;
  m_dwEvents = 0;
  m_eCursorType = (CursorTypeEnum)-2;
  m_eLockType = (LockTypeEnum)-2;
}

CAxRecordset::~CAxRecordset()
{
  if ( _IsOpen() )
    Close();

  if( m_piRecordset )
    m_piRecordset->Release();
  m_piRecordset = NULL;
}

///////////////////////////////////////////////////////////////
//	Initialization

// Method: Create
//   Desc: Creates and attacheds the underlying ADO Recordset object.
//         Create must be called before using the CAxRecordset object.
//
//   Args: none
//
// Return: void
//
//   v1.1: Moved call to Create internal to the Open method. Client
//         application no longer needs to call Create(). See note
//         in AxLib.h

HRESULT CAxRecordset::Create()
{
  HRESULT hr = CoCreateInstance(CLSID_CADORecordset, NULL, CLSCTX_INPROC_SERVER, 
              IID_IADORecordset15, (LPVOID *)&m_piRecordset);

	if FAILED( hr )
  {
    if ( m_piRecordset != NULL )
    {
      m_piRecordset->Release();
      m_piRecordset = NULL;
    }
  }

  return ( hr );
}

///////////////////////////////////////////////////////////////
//	AxLibSpecific

// Method: _ClearRecordsetEvents
//   Desc: Releases the ADO Events sink interface.
//
//   Args: none
//
// Return: void
//
void CAxRecordset::_ClearRecordsetEvents()
{
  if ( m_piRecordset == NULL || m_dwEvents == 0 )
    return;

  IConnectionPointContainer *pCPC = NULL;
  IConnectionPoint          *pCP = NULL;
  HRESULT hr = m_piRecordset->QueryInterface(__uuidof(IConnectionPointContainer),
    (LPVOID*)&pCPC);
  if FAILED(hr) 
	  ThrowAxException(AXLIB_ERROR_NONE, _T("Failed to create connection object"));

  hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
  pCPC->Release();
  if FAILED(hr)
		ThrowAxException(AXLIB_ERROR_NONE, _T("Failed to create connection object"));

  hr = pCP->Unadvise(m_dwEvents);
  pCP->Release();
  m_dwEvents--;
}

// Method: _IsEmpty
//   Desc: Indicates if there are any records in the recordset.
//
//   Args: none
//
// Return: True if the recordset is empty. Otherwise, false.
//
bool CAxRecordset::_IsEmpty()
{
	VALID_ADO_OBJECT(m_piRecordset);
	VARIANT_BOOL vbBOF = 0;
  VARIANT_BOOL vbEOF = 0;

	m_piRecordset->get_BOF(&vbBOF);
	m_piRecordset->get_EOF(&vbEOF);

  return ( (vbBOF<0) && (vbEOF<0) );
}

// Method: _IsOpen
//   Desc: Indicates if the recordset is currently open.
//
//   Args: none
//
// Return: True if the recordset is open. Otherwise, false.
//
bool CAxRecordset::_IsOpen()
{
  if ( m_piRecordset == NULL )
    return (FALSE);

	VALID_ADO_OBJECT(m_piRecordset);

  long lState;
  if FAILED( m_piRecordset->get_State(&lState) )
		ThrowAxException(AXLIB_ERROR_NONE);

  return (lState == adStateOpen);
}

// Method: _SetRecordsetEvents
//   Desc: Attaches the ADO Events sink interface allowing client
//         applications to handle ADO Recordset events. The host
//         program provides a specific implementation of the
//         CAxRecordsetEvents class to handle and respond to ADO
//         events that may be raised.
//
//   Args: CAxRecordsetEvents*
//          A reference to an AxLib Events object derive from
//          CAxRecordsetEvents.
//
// Return: void
//
void CAxRecordset::_SetRecordsetEvents(CAxRecordsetEvents* pEvents)
{
    IConnectionPointContainer *pCPC = NULL;
    IConnectionPoint          *pCP = NULL;
    HRESULT hr = m_piRecordset->QueryInterface(__uuidof(IConnectionPointContainer),
      (LPVOID*)&pCPC);
    if FAILED(hr) 
			ThrowAxException(AXLIB_ERROR_NONE, _T("Failed to create connection object"));

    hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
    pCPC->Release();
    if FAILED(hr)
			ThrowAxException(AXLIB_ERROR_NONE, _T("Failed to create connection object"));

    hr = pCP->Advise(pEvents, &m_dwEvents);
    pCP->Release();
}


///////////////////////////////////////////////////////////////
//	Collections

// Method: Fields
//   Desc: Returns a reference to the ADO Filelds collection.
//
//   Args: none
//
// Return: ADOFields*
//
ADOFields* CAxRecordset::Fields()
{
  return (m_pFields);
}

// Method: Properties
//   Desc: Returns a reference to the ADO Properties collection.
//
//   Args: none
//
// Return: ADOProperties*
//
ADOProperties* CAxRecordset::Properties()
{
	VALID_ADO_OBJECT(m_piRecordset);
  ADOProperties *pProps;

  HRESULT hr = m_piRecordset->get_Properties(&pProps);
  if FAILED( hr )
		ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Properties"), hr);

  return (pProps);
}


///////////////////////////////////////////////////////////////
//	Methods

// Method: AddNew
//   Desc: Creates a new blank record in the recordset. After
//         calling AddNew, the client application typically
//         completes the member variables of the CAxRecordset
//         derive class then calls the Update method to post
//         the new recordset information to the database.
//
//   Args: none
//
// Return: void
//
void CAxRecordset::AddNew()
{
	VALID_ADO_OBJECT(m_piRecordset);
  _variant_t vNames(DISP_E_PARAMNOTFOUND, VT_ERROR);
  _variant_t vValues(DISP_E_PARAMNOTFOUND, VT_ERROR);

  if ( Supports(adAddNew) )
  {
    HRESULT hr = m_piRecordset->AddNew(vNames, vValues);
	  if FAILED( hr )
		  ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Properties"), hr);
  }
}

// Method: Cancel
//   Desc: Cancels an asynchronous operation for the recordset object.
//
//   Args: none
//
// Return: void
//
void CAxRecordset::Cancel()
{
}

void CAxRecordset::CancelBatch()
{
}

// Method: CancelUpdate
//   Desc: Cancels editing of a record. A call to the CancelUpdate method
//         prior to calling Update will cancel any changes made to the
//         record since editing began. Additionally, if AddNew was called,
//         the creation of a new record is also canceled. With respect
//         to AxLib, a call to CancelUpdate is generally not needed since
//         changes are made to the local member variables. Any need to
//         cancel updating of the record would be handled in the client
//         application before making a call to the Update method.
//
//   Args: none
//
// Return: void
//
void CAxRecordset::CancelUpdate()
{
	VALID_ADO_OBJECT(m_piRecordset);
  HRESULT hr = S_OK;
	EditModeEnum	lEditMode;

  hr = m_piRecordset->get_EditMode(&lEditMode);
  if FAILED( hr )
    ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::CancelUpdate"), hr);

  if ( lEditMode == adEditInProgress || lEditMode == adEditAdd )
  {
    hr = m_piRecordset->CancelUpdate();
    if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::CancelUpdate"), hr);
  }
}

// Method: Clone
//   Desc: Return a duplicate copy of the underlying ADO Recordset object.
//
//   Args: eLockType
//     adLockUnspecified, (default)
//     adLockReadOnly
//
// Return: ADORecordset*
//
ADORecordset* CAxRecordset::Clone(LockTypeEnum eLockType)
{
	VALID_ADO_OBJECT(m_piRecordset);
  ADORecordset* pRec;

  HRESULT hr = m_piRecordset->Clone(eLockType, &pRec);
  if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Clone"), hr);

  return (pRec);
}

// Method: Close
//   Desc: Closes and open recordset. All dependent objects such as 
//         CAxRecordsetEvents, CAxCommand objects and the underlying
//         ADO Recordset object are closed as well.
//
//   Args: none
//
// Return: void
//
void CAxRecordset::Close()
{
	VALID_ADO_OBJECT(m_piRecordset);

  //Cleanup any related Command objects
  if ( m_pCommand )
  {
		if ( m_pCommand->m_piParameters )
		{
			m_pCommand->m_piParameters->Release();
			m_pCommand->m_piParameters = NULL;
		}
  	m_pCommand->m_piCommand->Release();
		m_pCommand->m_piCommand = NULL;
  }

  //Release Recordset events
  _ClearRecordsetEvents();

	if ( m_piRecordset && _IsOpen() )
	{
		m_piRecordset->MoveFirst();
		HRESULT hr = m_piRecordset->Close();
    
		if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Close"), hr);
	}
	
//	m_piRecordset->Release();
//	m_piRecordset = NULL;
}

// Method: CompareBookmarks
//   Desc: Determines the position of two bookmarks relative to one
//         another. A CompareEnum value is returned that indicates which
//         bookmark comes first in ordinal position.
//
//   Args: vtBkMark1, vtBkMark2
//          Bookmark variants to be compared.
//
// Return: A CompareEnum enumeration
//          adCompareLessThan	= 0,
//          adCompareEqual	= 1,
//          adCompareGreaterThan	= 2,
//          adCompareNotEqual	= 3,
//          adCompareNotComparable	= 4
//
CompareEnum CAxRecordset::CompareBookmarks(_variant_t vtBkMark1, _variant_t vtBkMark2)
{
 	VALID_ADO_OBJECT(m_piRecordset);
  CompareEnum eComp;

  HRESULT hr = m_piRecordset->CompareBookmarks(vtBkMark1, vtBkMark2, &eComp);
  if FAILED( hr )
    ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::CompareBookmarks"), hr);

  return (eComp);
}

// Method: Delete 
//   Desc: Deletes specified records in the recordset. In general the
//         client application will use the default of adAffectCurrent
//         to delete the current record only.
//
//   Args: eAffect
//          An AffectEnum value:
//            adAffectCurrent	= 1,
//            adAffectGroup	= 2,
//            adAffectAll	= 3,
//           dAffectAllChapters	= 4
//
// Return: void
//
void CAxRecordset::Delete(AffectEnum eAffect)
{
	VALID_ADO_OBJECT(m_piRecordset);
  HRESULT hr = S_OK;
	EditModeEnum	lEditMode;

	//Watch for empty recordset
	if ( _IsEmpty() )
		return;

	//Delete method depends on current mode
  hr = m_piRecordset->get_EditMode(&lEditMode);
	if FAILED( hr )
    ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Delete"), hr);

	switch (lEditMode)
  {
	case adEditNone: // Just delete it
    hr = m_piRecordset->Delete(eAffect);
	  if FAILED( hr )
    ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Delete"), hr);
		break;

	case adEditInProgress: //Forget changes
    hr = m_piRecordset->CancelUpdate();
		if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Delete"), hr);

    hr = m_piRecordset->Delete(eAffect);
	  if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Delete"), hr);
		break;

	case adEditAdd: //If new record, go back to last known
    hr = m_piRecordset->CancelUpdate();
		if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Delete"), hr);
    
    hr = m_piRecordset->put_Bookmark(m_varLastGoodRecord);
		if FAILED( hr )
      ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Delete"), hr);
    break;
	}
}

// Method: Find 
//   Desc: Performs a search based on a single column search criteria.
//         If successful, the record pointer is positioned on the 
//         first record to match the search criteria. The search
//         criteria matches that of the SQL WHERE clause, such as
//         "AccountID = 'ABC'". The client application should set the
//         record pointer by making a call to Move, MoveFirst, etc.
//
//   Args: strCriteria - search criteria
//         nSkip - number of rows to skip before searching
//         SearchDirectionEnum - determines the direction of the search
//            adSearchForward	= 1,
//            adSearchBackward = -1
//         pvtStart - bookmark used as a starting point for the search
//
// Return: true if match is found, otherwise false
//

bool CAxRecordset::Find(LPCTSTR lpszCriteria, long nSkip,
	         SearchDirectionEnum eSearchDirection, _variant_t* pvtStart)
{
	VALID_ADO_OBJECT(m_piRecordset);
	HRESULT hr;
	_bstr_t bstrCriteria(lpszCriteria);

  if ( _IsEmpty() )
    return ( false );

  if ( pvtStart )
	  hr = m_piRecordset->Find(bstrCriteria, nSkip, eSearchDirection, *pvtStart);
  else
	  hr = m_piRecordset->Find(bstrCriteria, nSkip, eSearchDirection, _variant_t(AbsolutePosition()));

  if FAILED( hr )
    ThrowAxException(AXLIB_ERROR_NONE, _T("CAxRecordset::Find"), hr);

  if ( IsBOF() || IsEOF() )
    return ( false );

	DoFieldExchange(FALSE);
	return ( true );
}

void CAxRecordset::GetRows()
{
}

void CAxRecordset::GetString()
{
}

// Method: Move 
//   Desc: Moves a specified number of records forward or backward
//         from the current position. If the resultant move is beyond
//         the end of the recordset or past the beginning, the 
//         record point is positioned just after the last record or
//         just before the first record, i.e. BOF/EOF.
//
//   Args: nNumRecs - number of records to move from the current position
//                    or that specified by the pvtStartRec bookmark
//         pvtStartRec - bookmark specifing the starting record position.
//                       The default is the current record, adBookmarkCurrent
//
// Return: void
//
void CAxRecordset::Move(long nNumRecs, _variant_t* pvtStartRec)
{
	VALID_ADO_OBJECT(m_piRecordset);

  HRESULT hr = S_OK;
  
  if ( pvtStartRec )
    hr = m_piRecordset->Move(nNumRecs, *pvtStartRec);
  else
    hr = m_piRecordset->Move(nNumRecs, _variant_t(0L));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -