在VC++ 6.0 环境下,直接用C(没用MFC)写了一个数据库访问程序。问题:    1  利用Recordset对象读取数据库中的字符串字段时,如何将通过GetCollect()得到的_variant_t类型(GetCollect()的返回值)转换为字符串(string或char*)?    2  在我的程序里,访问数据库的用户有INSERT,UPDATE,DELETE,SELECT等所有权限,但不能对表执行Add和Delete操作。Recordset的AddNew()和Delete()使用还有其它什么限制吗?如何Add和Delete呢?    #import "...\msado15.dll"    _ConnectionPtr pConnection;
    _RecordsetPtr pRecordset;    HRESULT hr;    if(FAILED(::CoInitialize(NULL))) 
        return -1;    try
    {
hr = pConnection.CreateInstance("ADODB.Connection");
pRecordset.CreateInstance( _uuidof(Recordset) ); if(SUCCEEDED(hr))
{
        _bstr_t connStr( "..." );
     hr = pConnection->Open( connStr,... );

        pRecordset->Open( ....);        pRecordset->MoveFirst();              // 调试时此句会出错。此时 _com_error 对象 e 的 __vfptr 为:
              //  0x004353d0 const _com_error::'vftable'
              // command 窗口出现的错误提示为:
              //  error : Unknown error 0x800A0CB3
        pRecordset->Delete(adAffectCurrent);      for( int i = 0; i < 2; ++i )
              {
                  // 调试时,能够在Watch窗口正确显示出 var1, var2 里面的          //  字符串信息。我的问题是:如何把它里面的字符串提出来
                  _variant_t var1 = pRecordset->GetCollect("aaa");
_variant_t var2 = pRecordset->GetCollect("bbb");                  // 调试时此句会出错,错误同调用Delete时一样  
pRecordset->AddNew();
pRecordset->PutCollect( "aaa", _variant_t("BX3Y2Z1") );
pRecordset->PutCollect( "bbb", _variant_t("HWI9214") );
     }
     
              pRecordset->Update();      pRecordset->Close();
     pConnection->Close();
}
    }
    catch(_com_error e)
    {
cout << "error : " << e.ErrorMessage() << endl;
    }     ::CoUninitialize();把 _variant_t 变量var1,var2 用Detatch()方法得到 VARIANT 变量结构体后,里面有一个类型为 char FAR* 的 pcVal 变量,直接输出该变量时只能得到两个字段里面的第一个字符(与表里对照,这是正确的)。

解决方案 »

  1.   

    注:上面的程序中凡出现“...”的地方均为略写,如果注释掉Delete()和Insert()相关部分,程序能够运行。
      

  2.   

    pRecordset->Delete(adAffectCurrent);
    之前判断pRecordset->BOF
      

  3.   

    转为 CString 的对象:(char*)(_bstr_t)GetCollect();
    还要看你的打开方式是否允许插入和删除?
      

  4.   

    各位大概是没看清我的前提条件:我是在C下而非MFC下,CString已不能用矣。当然,在MFC下这样是可以的。另:我注掉Delete句,直接到AddNew句也不行的。且Delete句是在MoveFirst句之后,而我的表中是有记录的。
        在MFC下,到Delete句时的错误为:Unknown error 0x800A0CB3;注掉Delete句,到AddNew句后错误一样。
      

  5.   

    to cdwy411(无心睡眠):
       ADO出错时的提示信息:IDispatch error #xxxx 在什么地方(MSDN?书籍?杂志?)可以找到?3x!
      

  6.   

    1、LPTSTR pszData=(LPTSTR)(_bstr_t)vtData; LPCTSTR pszData=(LPCTSTR)(_bstr_t)vtData
      

  7.   

    MFC下,第一点已经解决。现在把注意力转到第二点上来吧。我以 Recordset Open 句是这样的:
     
    pRecordset->Open("select * from boxInfo", connStr, adOpenDynamic, adLockOptimistic, adCmdText );第三个和第四个参数表明,我可以对进行增删操作。此时,try 段内的 for 循环能够执行一次,第二次 AddNew 时就会出错:{DB_E_INTEGRITYVIOLATION}    IDispatch error #3119不符合数据库的完整性约束。关于 Open 方法的第四个参数即 LockType,当其为 adLockOptimistic 时,MSDN说:Indicates optimistic locking, record by record. The provider uses optimistic locking, locking records only when you call the Update method.这里的所谓"lock"应当是指当我作出什么操作时,会"lock"住其它用户(线程)对该表(记录)的操作吧,而不是"lock"我自己对表的操作。也就是说,如果用 adLockOptimistic 的话,只有当我 Update 的时候,才会对表执行"lock"动作。
      

  8.   

    pRecordset->Open( ....);是什么
      

  9.   

    addnew的时候是不是把所有的字段都赋值了,如果非空的字段没有赋值或者给不允许更新的字段赋值便会出错
      

  10.   

    而且,有些字段的类型不匹配也会出错  ADO出错时的提示信息:IDispatch error #xxxx 在什么地方(MSDN?书籍?杂志?)可以找到?3x
    我也不知道在哪儿看的?VC 有个LookUp工具可以查看一些错误的
      

  11.   

    哦,搞定了:)原因在于表中的主键不允许修改,小弟数据库知识有限,不知道数据库是不是这样规定的。至少从程序的反应来看是这样的:我把字段 aaa 的主键标记去掉后,就能成功对其修改,即AddNew 调用成功。谢谢各位了。呵呵