首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VC/MFC >

ADO存取图片到SQL SERVER数据库时遇到的有关问题

2012-03-13 
ADO存取图片到SQL SERVER数据库时遇到的问题代码如下,前一段为存,后一段为取,存正常,取出错.另外,还有几个

ADO存取图片到SQL SERVER数据库时遇到的问题
代码如下,前一段为存,后一段为取,存正常,取出错.
另外,还有几个顺带的问题,1.AppendChunk,GetChunk是不是对所操作的字段的类型有要求,必须是text或image类型?我本来是想用这两方法来对所有类型进行操作的,   试了下,好象别的类型不行.2.另外,C++中类的公共成员,保护成员,私有成员命名时,前缀是什么,这个好象在哪里看过,忘了,也不知道是哪门语言上的,知道的也顺便说下
3.我在用ADO操作的时候,以前用catch(_com_err   e)这样捕捉,好象连一般的打开记录集Open出错时,都不会抛出,于是后来就一直用catch(...),不过,现在不知道怎么把错误码或详细信息读出来,在catch中用GetLastError好象不行,知道怎么用的也说下,谢谢


try
{

lstate   =   m_pRecordset-> State;
if(lstate   ==   adStateOpen)
m_pRecordset-> Close();
m_pRecordset-> Open((_bstr_t)szCommand,                                
m_pConnection.GetInterfacePtr(),  
adOpenDynamic,
adLockOptimistic,
adCmdText);


Fields   *pFields   =   m_pRecordset-> GetFields();
Field   *pField   =   pFields-> GetItem( "other3 ");


    CFile   imagefile;
    if(0   ==   imagefile.Open( "C:\\WINNT\\Blue   Lace   16.bmp ",CFile::modeRead))
  return;
    long   nLength   =   imagefile.GetLength();
    BYTE   *pbuf   =   NULL;
    BYTE   *pBufEx   =   NULL;


//存
    pbuf   =   new   BYTE[nLength];
    pBufEx   =   pbuf;
    if(pbuf   ==   NULL)
  return;                                                           //allocate   memory   error;
    imagefile.Read(pbuf,nLength);                     //read   the   file   into   memory

    //build   a   SAFFERRAY
    SAFEARRAY*   psa;
    SAFEARRAYBOUND   rgsabound[1];
    rgsabound[0].lLbound   =   0;
    rgsabound[0].cElements   =   nLength;
    psa   =   SafeArrayCreate(VT_UI1,   1,   rgsabound);

    for   (long   j   =   0;   j   <   nLength;   j++)
      SafeArrayPutElement   (psa,   &j,   pBufEx++);
    VARIANT   varBLOB;
    varBLOB.vt   =   VT_ARRAY   |   VT_UI1;
    varBLOB.parray   =   psa;
    pField-> AppendChunk(varBLOB);
    delete   []pbuf;


//取

VARIANT   varBLOB2;
pField-> get_ActualSize(&nLenth);     //这里取出来的长度和上面存入的长度一致
varBLOB2   =   pField-> GetChunk(nLenth);     //运行到这句的时候,异常抛出.
if(varBLOB2.vt   ==   (VT_ARRAY   |   VT_UI1))                
{    
pbuf   =   (BYTE*)GlobalAlloc(GMEM_FIXED,nLenth);
SafeArrayAccessData(varBLOB2.parray,(void   **)pbuf);    

                        //Build   a   File   in   Windows   Temp   Directory
                        char   tmpPath[_MAX_PATH+1];
                        GetTempPath(_MAX_PATH,tmpPath);


                        CString   strFileName   =   "temp.bmp ";
                        strFileName   =   tmpPath+strFileName;
                                                                           
                        CFile   outFile(strFileName,CFile::modeCreate|CFile::modeWrite);
                        LPSTR   buffer   =   (LPSTR)GlobalLock((HGLOBAL)pbuf);
                        outFile.WriteHuge(buffer,nLenth);
                        GlobalUnlock((HGLOBAL)pbuf);
                        outFile.Close();          

SafeArrayUnaccessData   (varBLOB2.parray);
}

}
catch(...)
{
AfxMessageBox( "E ");
}

[解决办法]
虽然从你的上下文看不出你为什么要用这个GlobalAlloc,可能你是想使用全局堆分配空间获取足够大的内存块来存取数据。

至于我用API来存取文件,是因为习惯。使用CFile只是另外一种方式而已。

LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pbuf);
这一句比较可疑,因为pbuf是从安全数组对象里取得的一个指向内存块的指针,而HGLOBAL是一个由GlobalAlloc得到的标识一个全局内存块句柄,应该不能直接转换,除非pbuf是这样得来的
pbuf = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih-> biSizeImage);但显然不是的

另外呢outFile.WriteHuge(buffer,nLenth);这个方法已经不常用了,已经被Write所替代。

LPSTR buffer = (LPSTR)GlobalLock((HGLOBAL)pbuf);这个强制转换很可疑,因为对于HGLOBAL指向的内存结构实际上应该是一个结构体,包含了一个计数器,依靠增减这个引用计数器来保护这个内存块,感觉有些问题

虽然不知道你为什么使用GlobalLock这一族的API,可能是因为有多进程或者多线程需要访问同一块内存

但是你读取数据库BLOB字段,用这种方式好像并不是很好。


热点排行