📄 updatableproxyrowsetimpl.h
字号:
#ifndef __UPDATABLE_PROXY_ROWSET_IMPL__INCLUDED__
#define __UPDATABLE_PROXY_ROWSET_IMPL__INCLUDED__
#include "ProxyRowsetImpl.h"
#include "IRowsetChangeImpl.h"
#include "IColumnsRowsetImpl.h"
///////////////////////////////////////////////////////////////////////////////
// CUpdatableProxyRowsetImpl
// An ATL OLE DB Provider template that represents an updatable Rowset which
// expects the derived class to be responsible for storing the rowset data
// within it (rather than working with the Storage and ArrayType classes).
///////////////////////////////////////////////////////////////////////////////
template <
class DataClass,
class T,
class CreatorClass,
class Storage = CRowsetStorageProxy<T>,
class ArrayType = CRowsetArrayTypeProxy<T, Storage>,
class RowClass = CSimpleRow,
class RowsetInterface = IRowsetImpl < T, IRowset, RowClass> >
class CUpdatableProxyRowsetImpl:
public CProxyRowsetImpl< DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface >,
public IRowsetChangeImpl<T, Storage>,
public IConnectionPointContainerImpl<CUpdatableProxyRowsetImpl>,
public IColumnsRowsetImpl<T, CreatorClass>
{
public:
friend Storage;
friend ArrayType;
typedef CreatorClass::_PropClass _PropClass ;
typedef CUpdatableProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface> UpdatableProxyRowsetClass;
BEGIN_COM_MAP(CUpdatableProxyRowsetImpl)
COM_INTERFACE_ENTRY(IRowsetChange)
COM_INTERFACE_ENTRY(IConnectionPointContainer)
COM_INTERFACE_ENTRY(IColumnsRowset)
COM_INTERFACE_ENTRY_CHAIN(ProxyRowsetClass)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(CUpdatableProxyRowsetImpl)
CONNECTION_POINT_ENTRY(IID_IRowsetNotify)
END_CONNECTION_POINT_MAP()
CUpdatableProxyRowsetImpl();
~CUpdatableProxyRowsetImpl();
HRESULT SetDataHelper(
HROW hRow,
HACCESSOR hAccessor,
void *pSrcData,
bool bSendNotifications);
protected :
virtual void UpdateColumn(
size_t row,
size_t column,
void *pData) = 0;
private :
void InternalUpdateColumn(
size_t row,
size_t column,
void *pData);
};
///////////////////////////////////////////////////////////////////////////////
// Construction and destruction...
///////////////////////////////////////////////////////////////////////////////
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
CUpdatableProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::CUpdatableProxyRowsetImpl()
{
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
CUpdatableProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::~CUpdatableProxyRowsetImpl()
{
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
void CUpdatableProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::InternalUpdateColumn(
size_t row,
size_t column,
void *pData)
{
ATLASSERT(column != 0); // Nobody should ever try to write to the bookmark column!
UpdateColumn(row, column - 1, pData);
}
template <class DataClass, class T, class CreatorClass, class Storage, class ArrayType, class RowClass, class RowsetInterface>
HRESULT CUpdatableProxyRowsetImpl<DataClass, T, CreatorClass, Storage, ArrayType, RowClass, RowsetInterface>::SetDataHelper(
HROW hRow,
HACCESSOR hAccessor,
void *pSrcData,
bool bSendNotifications)
{
ATLTRACE2(atlTraceDBProvider, 0, "CUpdatableRowsetImpl::SetDataHelper() - hRow = %d\n", hRow);
RowClass* pRow = 0;
if (hRow == 0 || (pRow = m_rgRowHandles.Lookup((RowClass::KeyType)hRow)) == NULL)
{
ATLTRACE2(atlTraceDBProvider, 0, "CUpdatableRowsetImpl::SetDataHelper - Error - Bad row handle\n");
return DB_E_BADROWHANDLE;
}
_BindType *pBinding = m_rgBindings.Lookup((int)hAccessor);
if (pBinding == NULL)
{
return DB_E_BADACCESSORHANDLE;
}
// convert the pBinding structure into an array of ULONG of column ordinals
ULONG *rgColumns = 0;
CAutoMemRelease<ULONG> crapHelper(rgColumns);
if (bSendNotifications)
{
rgColumns = new ULONG[pBinding->cBindings];
for (size_t i = 0; i < pBinding->cBindings; i++)
{
rgColumns[i] = pBinding->pBindings[i].iOrdinal;
}
if (!SendPreSetDataNotifications(hRow, pBinding->cBindings, rgColumns))
{
ATLTRACE2(atlTraceDBProvider, 0, "CUpdatableRowsetImpl::SetDataHelper - cancelled\n", pBinding->cBindings);
return DB_E_CANCELED;
}
}
HRESULT hr = S_OK;
for (ULONG iBind =0; SUCCEEDED(hr) && iBind < pBinding->cBindings; iBind++)
{
DBBINDING* pBindCur = &(pBinding->pBindings[iBind]);
ATLTRACE2(atlTraceDBProvider, 0, "CUpdatableRowsetImpl::SetDataHelper - Bindings for column ordinal %d\n", pBindCur->iOrdinal);
if (pBindCur->iOrdinal > GetNumColumns())
{
ATLTRACE2(atlTraceDBProvider, 0, "CUpdatableRowsetImpl::SetDataHelper - Error - bad ordinal\n");
return DB_E_BADORDINAL;
}
BOOL bProvOwn = (pBindCur->dwMemOwner == DBMEMOWNER_PROVIDEROWNED);
if (bProvOwn)
{
ATLTRACE2(atlTraceDBProvider, 0, "CUpdatableRowsetImpl::SetDataHelper - Error - we dont support provider owned memory\n");
return E_FAIL;
}
DBSTATUS dbStat = DBSTATUS_S_OK;
ULONG cbDst = pBindCur->cbMaxLen;
// This isn't relevant for strings as they can grow in size...
// TODO: surely we should be using the size of the data as specified in the binding here?
ULONG cbCol;
DBTYPE colType;
void *pData = 0;
bool bUpdatable = false;
InternalGetColumnData(pRow->m_iRowset, pBindCur->iOrdinal, colType, cbCol, pData, bUpdatable);
if (pBindCur->dwPart & DBPART_VALUE)
{
// TODO: - get this to allocate the buffer as needed and make it the right size...
// We could write straight into the memory of the derived class if we like (well
// for stuff that's not translated or variable length...
const size_t cBufferSize = 256;
BYTE horribleBuffer[cBufferSize];
BYTE *pSrcTemp = (BYTE*)pSrcData + pBindCur->obValue;
BYTE *pDstTemp = horribleBuffer;
if (bUpdatable)
{
pDstTemp = (BYTE*)pData;
}
hr = m_spConvert->DataConvert(
pBindCur->wType, // the source type
colType, // the required type
cbCol, // length of column data
&cbDst, // length of data after conversion
pSrcTemp, // pointer to the column data
pDstTemp, // pointer to where to put it...
cBufferSize, // max length of destination buffer
dbStat, // source status
&dbStat, // dest status
pBindCur->bPrecision, // precision
pBindCur->bScale, // scale
0); // flags - none supplied
if (!bUpdatable)
{
InternalUpdateColumn(pRow->m_iRowset, pBindCur->iOrdinal, pDstTemp);
}
}
}
if (bSendNotifications)
{
if (SUCCEEDED(hr))
{
SendPostSetDataNotifications(hRow, pBinding->cBindings, rgColumns);
}
else
{
SendFailedSetDataNotifications(hRow, pBinding->cBindings, rgColumns);
}
}
return hr;
}
#endif // __UPDATABLE_ROWSET_IMPL__INCLUDED__
///////////////////////////////////////////////////////////////////////////////
// End of file...
///////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -