📄 axrecordset.cpp
字号:
#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 + -