学院首页>网络编程>SQL Server>Visual C++中使用OLE DB读写SQL Server简明指南

Visual C++中使用OLE DB读写SQL Server简明指南

作者: 来源: 添加时间:2006-5-24 13:32:54

  以上就是写数据库的全部代码了,是不是很简单呢?下面再来读的。

  // 先用与上面代码中一样的步骤获取pICommand,pICommandText。此处省略

  HRESULT hResult = pICommandText->SetCommandText( DBGUID_DBSQL, ( LPCOLESTR )_T("SELECT Volume FROM 2005_1 WHERE ID = @@IDENTITY") ); //取我们刚刚添加的那一条记录
  if( FAILED( hResult ) )
  {
  return;
  }

  LONG lAffected;
  EAutoReleasePtr pIRowset;
  hResult = pICommand->Execute( NULL, IID_IRowset, NULL, &lAffected, ( IUnknown** )&pIRowset );

  if( FAILED( hResult ) )
  {
  return;
  }

  EAutoReleasePtr pIAccessor;
  hResult = pIRowset->QueryInterface( IID_IAccessor, ( void** )&pIAccessor );

  if( FAILED( hResult ) )
  {
  return;
  }

  // 一个根据表中各字段的数值类型而定义的结构,用于存储返回的各字段的值
  struct CLoadLastFromDB
  {
  DBSTATUS dwdsVolume;
  DWORD dwLenVolume;
  float fVolume;
  };

  // 此处我们只查询了一个字段。如果要查询多个字段,CLoadLastFromDB中要添加相应的字段定义,下面的dbBinding也要相应扩充。dbBinding[].iOrdinal要分别指向各个字段,dbBinding[].wType要根据字段类型赋合适的值。

  DBBINDING dbBinding[1];
  dbBinding[0].iOrdinal = 1; // Volume 字段的位置,从 1 开始
  dbBinding[0].obValue = offsetof( CLoadLastFromDB, fVolume );
  dbBinding[0].obLength = offsetof( CLoadLastFromDB, dwLenVolume );
  dbBinding[0].obStatus = offsetof( CLoadLastFromDB, dwdsVolume );
  dbBinding[0].pTypeInfo = NULL;
  dbBinding[0].pObject = NULL;
  dbBinding[0].pBindExt = NULL;
  dbBinding[0].dwPart = DBPART_VALUE | DBPART_STATUS | DBPART_LENGTH;
  dbBinding[0].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
  dbBinding[0].eParamIO = DBPARAMIO_NOTPARAM;
  dbBinding[0].cbMaxLen = 0;
  dbBinding[0].dwFlags = 0;
  dbBinding[0].wType = DBTYPE_R4; // float就是DBTYPE_R4,int就是DBTYPE_I4。参见MSDN
  dbBinding[0].bPrecision = 0;
  dbBinding[0].bScale = 0;

  HACCESSOR hAccessor = DB_NULL_HACCESSOR;
  DBBINDSTATUS dbs[1];
  hResult = pIAccessor->CreateAccessor( DBACCESSOR_ROWDATA, 1, dbBinding, sizeof( CLoadLastDataFromDB ), &hAccessor, dbs );

  if( FAILED( hResult ) )
  {
  return;
  }

  ASSERT( dbs[0] == DBBINDSTATUS_OK );
  ULONG uRowsObtained = 0;
  HROW hRows[1]; // 这里我们只查询了最新的那一条记录
  HROW* phRows = hRows;
  CLoadLastFromDB rmd;
  hResult = pIRowset->GetNextRows( NULL, 0, 1, &uRowsObtained, &phRows );
  if( SUCCEEDED( hResult ) && uRowsObtained != 0U )
  {
  hResult = pIRowset->GetData( phRows[0], hAccessor, &rmd );
  if( FAILED( hResult ) )
  {
  ASSERT( FALSE );
  }
  ASSERT( rmd.dwdsVolume == DBSTATUS_S_OK );
  // rmd.fVolume 就是我们要取的值
  }

  pIRowset->ReleaseRows( uRowsObtained, phRows, NULL, NULL, NULL );
  pIAccessor->ReleaseAccessor( hAccessor, NULL );
  pIAccessor.Release( );
  pIRowset.Release( );

  读操作也完成了,是不是仍然很简单呢?下面我们再来看看最麻烦的二进制数据(text、ntext、image等)的读写。要实现BLOB数据的读写,我们需要一个辅助的类,定义如下:

  class CSequentialStream : public ISequentialStream // BLOB 数据访问类
  {
  public:
  CSequentialStream( );
  virtual ~CSequentialStream( );
  virtual BOOL Seek( ULONG uPosition );
  virtual BOOL Clear( );
  virtual ULONG GetLength( ) { return m_uBufferUsed; };
  virtual operator void* const( ) { return m_pBuffer; };
  STDMETHODIMP_( ULONG ) AddRef( ) { return ++ m_uRefCount; };
  STDMETHODIMP_( ULONG ) Release( ) { ASSERT( m_uRefCount != 0U ); -- m_uRefCount; if( m_uRefCount == 0U ) { delete this; } return m_uRefCount; };
  STDMETHODIMP QueryInterface( REFIID riid, LPVOID* ppv );
  STDMETHODIMP Read( void __RPC_FAR* pv, ULONG cb, ULONG __RPC_FAR* pcbRead );
  STDMETHODIMP Write( const void __RPC_FAR* pv, ULONG cb, ULONG __RPC_FAR* pcbWritten );
  void ResetPosition( ) { m_uPosition = 0U; };
  HRESULT PreAllocBuffer( ULONG uSize );

  private:
  ULONG m_uRefCount; // reference count
  void* m_pBuffer; // buffer
  ULONG m_uBufferUsed; // buffer used
  ULONG m_uBufferSize; // buffer size
  ULONG m_uPosition; // current index position in the buffer
  };
第 2 页,共 2 页 [1] [2]
站内搜索