本人曾遇到一个非常棘手的问题,在VC中用OLE DB读写SQL Server中的BLOB字段时,尝试了几乎所有的绑定方法,读是没有问题,但总无法成功地将数据写入BLOB中的字段中。后来在SQL Server的Books OnLines中找到一些提示,经多次实验,终于成功地解决问题。在这里提供源代码供大家参考。
首先,应当从ISequentialStream派生一个类,其头文件如下(SeqStream.h):
//SeqStream.h
#if !defined (CSEQSTREAM_H)
#define CSEQSTREAM_H
class CSeqStream : public ISequentialStream
{
public:
//Constructors
CSeqStream();
virtual ~CSeqStream();
virtual BOOL Seek(ULONG iPos);
virtual BOOL Clear();
virtual BOOL CompareData(void* pBuffer);
virtual ULONG Length() { return m_cBufSize; };
virtual operator void* const() { return m_pBuffer; };
STDMETHODIMP_(ULONG) AddRef(void);
STDMETHODIMP_(ULONG) Release(void);
STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv);
STDMETHODIMP Read(
/* [out] */ void __RPC_FAR *pv,
/* [in] */ ULONG cb,
/* [out] */ ULONG __RPC_FAR *pcbRead);
STDMETHODIMP Write(
/* [in] */ const void __RPC_FAR *pv,
/* [in] */ ULONG cb,
/* [out]*/ ULONG __RPC_FAR *pcbWritten);
void ResetPosition();
protected:
//Data
private:
ULONG m_cRef; // reference count
void* m_pBuffer; // buffer
ULONG m_cBufSize; // buffer size
ULONG m_iPos; // current index position in the buffer
};
#endif
实现文件如下(SeqStream.cpp):
#include "stdafx.h"
#include "SeqStream.h "
CSeqStream::CSeqStream()
{
m_iPos = 0;
m_cRef = 0;
m_pBuffer = NULL;
m_cBufSize = 0;
//The constructor AddRef's
AddRef();
}
CSeqStream::~CSeqStream()
{
//Shouldn't have any references left
// ASSERT(m_cRef == 0);
CoTaskMemFree(m_pBuffer);
}
ULONG CSeqStream::AddRef(void)
{
return ++m_cRef;
}
ULONG CSeqStream::Release(void)
{
// ASSERT(m_cRef);
if(--m_cRef)
return m_cRef;
delete this;
return 0;
}
HRESULT CSeqStream::QueryInterface(REFIID riid, void** ppv)
{
// ASSERT(ppv);
*ppv = NULL;
if (riid == IID_IUnknown)
*ppv = this;
if (riid == IID_ISequentialStream)
*ppv = this;
if(*ppv)
{
((IUnknown*)*ppv)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
BOOL CSeqStream::Seek(ULONG iPos)
{
//Make sure the desired position is within the buffer
// ASSERT(iPos == 0 || iPos < m_cBufSize);
//Reset the current buffer position
m_iPos = iPos;
return TRUE;
}
BOOL CSeqStream::Clear()
{
//Frees the buffer
m_iPos = 0;
m_cBufSize = 0;
CoTaskMemFree(m_pBuffer);
m_pBuffer = NULL;
return TRUE;
}
BOOL CSeqStream::CompareData(void* pBuffer)
{
// ASSERT(pBuffer);
//Quick and easy way to compare user buffer with the stream
return memcmp(pBuffer, m_pBuffer, m_cBufSize)==0;
}
HRESULT CSeqStream::Read(void *pv, ULONG cb, ULONG* pcbRead)
{
//Parameter checking
if(pcbRead)
*pcbRead = 0;
if(!pv)
return STG_E_INVALIDPOINTER;
if(cb == 0)
return S_OK;
//Actual code
ULONG cBytesLeft = m_cBufSize - m_iPos;
ULONG cBytesRead = cb > cBytesLeft ? cBytesLeft : cb;
//if no more bytes to retrieve return
if(cBytesLeft == 0)
return S_FALSE;
//Copy to users buffer the number of bytes requested or remaining
memcpy(pv, (void*)((BYTE*)m_pBuffer + m_iPos), cBytesRead);
m_iPos += cBytesRead;
if(pcbRead)
*pcbRead = cBytesRead;
if(cb != cBytesRead)
return S_FALSE;
return S_OK;
}
HRESULT CSeqStream::Write(const void *pv, ULONG cb, ULONG* pcbWritten)
{
//Parameter checking
if(!pv)
return STG_E_INVALIDPOINTER;
if(pcbWritten)
*pcbWritten = 0;
if(cb == 0)
return S_OK;
//Enlarge the current buffer
m_cBufSize += cb;
//Need to append to the end of the stream
m_pBuffer = CoTaskMemRealloc(m_pBuffer, m_cBufSize);
memcpy((void*)((BYTE*)m_pBuffer + m_iPos), pv, cb);
m_iPos += cb;
if(pcbWritten)
*pcbWritten = cb;
return S_OK;
}
void CSeqStream::ResetPosition()
{
m_iPos=0;
}
设要从一个文件读数据写入到数据库中的一个BLOB字段,在SQL Server中的Table名为tMaterials,它的Key为MaterialID,BLOB字段名为Stream。 写入BL
|