OleVariant类型变量在Midas中传输问题,请关注!!!(在线等待)

时间:2023-01-26 18:38:56
在服务器端一个remote datamodule,上面放置TADOConnection *ADOConnection1;  TADOQuery *ADOQuery1; TDataSetProvider *DataSetProvider1;,并定义取数据的方法QueryData,更新数据的方法UpData,因为在Midas下不支持OleVariant只支持VARIANT和VARIANT *,我做了转换,在取的数据是否报“invalid data packet”的错误,,在更新的时候却更新失败。而同样的功能在用Delphi做却一点问题都没有,并不用进行类型转换。演示源码如下:
// 取数据
服务器端:
STDMETHODIMP TMyRmdFooImpl::QueryData(VARIANT* Value)
{
    // Value为out和retval
try
    {
        OleVariant Result;
        m_DataModule->ADOQuery1->Active = false;
m_DataModule->ADOQuery1->Open();
Result = m_DataModule->DataSetProvider1->Data;
Value= reinterpret_cast<VARIANTOBJ*>(&Result);
    }
    catch(Exception &e)
    {
        return Error(e.Message.c_str(), IID_IMyRmdFoo);
    }
    return S_OK;
}

客户端:
void __fastcall TForm1::Button1Click(TObject *Sender)
{

    IDispatch *disp = (IDispatch*)(SocketConnection1->AppServer);
    IMyRmdFooDisp V((IMyRmdFoo*)disp);
    try
    {
        try
        {
            OleVariant *Varr = new OleVariant();
            VARIANTOBJ * a= reinterpret_cast< VARIANTOBJ *>(Varr);
            if( V.GetOleDataSet(a) == S_OK )
            {
                ClientDataSet1->Data = *Varr;
                ShowMessage("数据取得成功!");
            }
            else
            {
               ShowMessage("数据取得失败");
            }
        }
        catch ( ... )
        {
            ShowMessage("远程调用失败");
        }
    }
    __finally
    {
        V.Unbind( );
    }
}

// 更新数据

// 服务器端
STDMETHODIMP TMyRmdFooImpl::UpData(short hCnd, VARIANT* Value)
{

        int ErrCount=0;
        m_DataModule->ADOConnection1->BeginTrans();
        try
        {
            OleVariant & vCustVar = *(reinterpret_cast<OleVariant *>(Value));
            if(!vCustVar.IsNull())
            {
                ErrCount=0;                m_DataModule->DataSetProvider2->ApplyUpdates(vCustVar,0,ErrCount,vCustVar);
                if(ErrCount>0)
                   return Error("Error in ApplyUpdates",IID_IMyRmdFoo);
            }
            m_DataModule->ADOConnection1->CommitTrans();
        }
        catch(Exception &e)
        {
           m_DataModule->ADOConnection1->RollbackTrans();
            return Error(e.Message.c_str(),IID_IMyRmdFoo);
        }
        return S_OK;
    }
    catch(Exception &e)
    {
        return Error(e.Message.c_str(), IID_IMyRmdFoo);
    }
    return S_OK;
     */
}
// 客户端
void __fastcall TForm1::Button3Click(TObject *Sender)
{
    OleVariant CustVar;
    if(ClientDataSet2->ChangeCount>0)
            CustVar=ClientDataSet2->Delta;
    else
        CustVar.ChangeType(VT_NULL);
    IDispatch *disp = (IDispatch*)(SocketConnection1->AppServer);
    IMyRmdFooDisp srvr((IMyRmdFoo*)disp);
    try
    {
        try
        {
            if(srvr.UpData(reinterpret_cast<VARIANTOBJ*>(&CustVar))==S_OK)
            {
                ShowMessage("更新成功&iexcl;");
                ClientDataSet2->MergeChangeLog();
            }
            else
            {
                ShowMessage("更新失败&iexcl;");
            }
        }
        catch(Exception & exception)
        {
            Application->ShowException( & exception) ;
        }

    }
    __finally
    {
        srvr.Unbind();
    }
}

27 个解决方案

#1


自己定一下

#2


呵呵, 你的代码风格是delphi, 很多情况下这样在bcb中可以使用, 不过在com方面却不行.

给你推荐一个网站, 上面的文章非常不错, 肯定可以帮助你

http://mental.mentsu.com/tech/tech.htm

#3


to  Aweay(char* love,int len):
我曾经看过你所推荐的网站,你的文章确实不错,不知你是否在将服务器上的TDataSetProvider的data属性,通过调用服务器的方法传递给客户端的ClientDataSet使用方面有好的解决办法(不是通过设置ClientDataSet的ProviderName的方法).多谢!

#4


应该这样:

STDMETHODIMP TMyRmdFooImpl::QueryData(VARIANT* Value)
{
    // Value为out和retval
try
    {
        TVariant Result;
        m_DataModule->ADOQuery1->Active = false;
        m_DataModule->ADOQuery1->Open();
        Result = m_DataModule->DataSetProvider1->Data;
        VariantCopy(Value,&Result);
    }
    catch(Exception &e)
    {
        return Error(e.Message.c_str(), IID_IMyRmdFoo);
    }
    return S_OK;
}

#5


客户端:
void __fastcall TForm1::Button1Click(TObject *Sender)
{

    IDispatch *disp = (IDispatch*)(SocketConnection1->AppServer);
    IMyRmdFooDisp V((IMyRmdFoo*)disp);
    try
    {
        try
        {
            TVariant tr;
            if( V.GetOleDataSet(&tr) == S_OK )
            {
                ClientDataSet1->Data = tr;
                ShowMessage("数据取得成功!");
            }
            else
            {
               ShowMessage("数据取得失败");
            }
        }
        catch ( ... )
        {
            ShowMessage("远程调用失败");
        }
    }
    __finally
    {
        V.Unbind( );
    }
}

#6


to  ljianq(泉深水清) :
在客户端调用的时候“ClientDataSet1->Data = tr;”,报ac 错误;是否不能将TVariant变量直接转换成OleVariant变量

#7


从帮助中知道:
Note: TVariantT and TVariant are used to represent COM arguments and interfaces, just like the OleVariant class.  However, TVariantT and TVariant are designed to work with C++Builder’s COM implementation classes that use the ATL, while OleVariant works with the VCL’s COM support.

#8


自己UP

#9


这几天忙着就职, 没有时间回复, 请见谅.

#10


to  Aweay(char* love,int len:
期待你的高见

#11


请各位大侠,多多指点迷津

#12


自己UP

#13


这个问题我刚刚也在研究,我是这样改的,你可以参考一下.
服务器:
1、将参数VARIANT* 改为VARIANT。
STDMETHODIMP TMyRmdFooImpl::UpData(short hCnd, VARIANT* Value)
改为
STDMETHODIMP TMyRmdFooImpl::UpData(short hCnd, VARIANT Value)
2、
 OleVariant & vCustVar = *(reinterpret_cast<OleVariant *>(Value));
改为
 OleVariant & vCustVar = *(reinterpret_cast<OleVariant *>(&Value));
// 客户端
            if(srvr.UpData(reinterpret_cast<VARIANTOBJ*>(&CustVar))==S_OK)

            if(srvr.UpData((VARIANT)CustVar)==S_OK)

#14


to  Cuiyc(阿昌) :如果从服务器段取数据如何修改?你能简单说一下你这样改的理由吗?

#15


好几天没上来了,才看见不好意思了.
上面的改法是我试出来了,理由我也不知道,我总觉得BCB这里可能是个BUG.
从服务器取数据你可以加入一个ClientDataSet控件.

#16


请问楼主是否在BCB6.0下编译?应该是吧,如果你采用这种方式update我建议你把程序挪到BCB5.0下重新编译一次应该就不会有问题了,以前我也有你同样的问题,弄了很久都没结果,后来在一位csdn上的朋友的提醒下,试着由BCB6.0转到BCB5.0去就解决了,可能是BCB6.0的Bug,或许是我没有找到办法,请那位兄台有BCB6.0上的解决方案望告知,先谢了!!!

#17


我在CB5的帮助中看到过使用OleVariant有时不能更新,但不知如何解决,帮助文件中也未作说明,不知在CB6中怎样

#18


to  cuptbluesky(苦行僧):
确实是在BCB6下

#19


请关注

#20


哈哈,原来都没有解决。

#21


to  yesry(噎死你):不知你有何高见

#22


换在BCB5下应该没问题

#23


楼主:
我对ljianq(泉深水清) 先生的例子进行了测试,应用层没有问题.客户层我做了如下修改,
在BCB6中测试没问题.改动如下:
    ITest11ServerDisp V;
    V.Bind(LPDISPATCH(DCOMConnection1->AppServer)) ;
    try
    {
        try
        {
            TVariant tr;
            if( V->QueryData(tr) == S_OK )
            {
                ClientDataSet1->Data = tr;
                ShowMessage("数据取得成功!");
            }
            else
            {
               ShowMessage("数据取得失败");
            }
        }
        catch ( ... )
        {
            ShowMessage("远程调用失败");
        }
    }
    __finally
    {
        V.Unbind( );
    }

#24


bcb6和bcb5的区别实在是。。。?

#25


请继续gz

#26


呵呵, Cuiyc(阿昌)兄请问你测试了数据的更新提交吗?在查询模式式下BCB6.0没有问题,可是提交数据更新时问题却来了,如果你有好解决方案能共享吗?

#27


好像在bcb 6中对OleVariant不能修改,但是在DataSetProvide中的更新Update中为什么有OleVariant变量,它又是处理的?请各位大侠能否提供参考意见

#1


自己定一下

#2


呵呵, 你的代码风格是delphi, 很多情况下这样在bcb中可以使用, 不过在com方面却不行.

给你推荐一个网站, 上面的文章非常不错, 肯定可以帮助你

http://mental.mentsu.com/tech/tech.htm

#3


to  Aweay(char* love,int len):
我曾经看过你所推荐的网站,你的文章确实不错,不知你是否在将服务器上的TDataSetProvider的data属性,通过调用服务器的方法传递给客户端的ClientDataSet使用方面有好的解决办法(不是通过设置ClientDataSet的ProviderName的方法).多谢!

#4


应该这样:

STDMETHODIMP TMyRmdFooImpl::QueryData(VARIANT* Value)
{
    // Value为out和retval
try
    {
        TVariant Result;
        m_DataModule->ADOQuery1->Active = false;
        m_DataModule->ADOQuery1->Open();
        Result = m_DataModule->DataSetProvider1->Data;
        VariantCopy(Value,&Result);
    }
    catch(Exception &e)
    {
        return Error(e.Message.c_str(), IID_IMyRmdFoo);
    }
    return S_OK;
}

#5


客户端:
void __fastcall TForm1::Button1Click(TObject *Sender)
{

    IDispatch *disp = (IDispatch*)(SocketConnection1->AppServer);
    IMyRmdFooDisp V((IMyRmdFoo*)disp);
    try
    {
        try
        {
            TVariant tr;
            if( V.GetOleDataSet(&tr) == S_OK )
            {
                ClientDataSet1->Data = tr;
                ShowMessage("数据取得成功!");
            }
            else
            {
               ShowMessage("数据取得失败");
            }
        }
        catch ( ... )
        {
            ShowMessage("远程调用失败");
        }
    }
    __finally
    {
        V.Unbind( );
    }
}

#6


to  ljianq(泉深水清) :
在客户端调用的时候“ClientDataSet1->Data = tr;”,报ac 错误;是否不能将TVariant变量直接转换成OleVariant变量

#7


从帮助中知道:
Note: TVariantT and TVariant are used to represent COM arguments and interfaces, just like the OleVariant class.  However, TVariantT and TVariant are designed to work with C++Builder’s COM implementation classes that use the ATL, while OleVariant works with the VCL’s COM support.

#8


自己UP

#9


这几天忙着就职, 没有时间回复, 请见谅.

#10


to  Aweay(char* love,int len:
期待你的高见

#11


请各位大侠,多多指点迷津

#12


自己UP

#13


这个问题我刚刚也在研究,我是这样改的,你可以参考一下.
服务器:
1、将参数VARIANT* 改为VARIANT。
STDMETHODIMP TMyRmdFooImpl::UpData(short hCnd, VARIANT* Value)
改为
STDMETHODIMP TMyRmdFooImpl::UpData(short hCnd, VARIANT Value)
2、
 OleVariant & vCustVar = *(reinterpret_cast<OleVariant *>(Value));
改为
 OleVariant & vCustVar = *(reinterpret_cast<OleVariant *>(&Value));
// 客户端
            if(srvr.UpData(reinterpret_cast<VARIANTOBJ*>(&CustVar))==S_OK)

            if(srvr.UpData((VARIANT)CustVar)==S_OK)

#14


to  Cuiyc(阿昌) :如果从服务器段取数据如何修改?你能简单说一下你这样改的理由吗?

#15


好几天没上来了,才看见不好意思了.
上面的改法是我试出来了,理由我也不知道,我总觉得BCB这里可能是个BUG.
从服务器取数据你可以加入一个ClientDataSet控件.

#16


请问楼主是否在BCB6.0下编译?应该是吧,如果你采用这种方式update我建议你把程序挪到BCB5.0下重新编译一次应该就不会有问题了,以前我也有你同样的问题,弄了很久都没结果,后来在一位csdn上的朋友的提醒下,试着由BCB6.0转到BCB5.0去就解决了,可能是BCB6.0的Bug,或许是我没有找到办法,请那位兄台有BCB6.0上的解决方案望告知,先谢了!!!

#17


我在CB5的帮助中看到过使用OleVariant有时不能更新,但不知如何解决,帮助文件中也未作说明,不知在CB6中怎样

#18


to  cuptbluesky(苦行僧):
确实是在BCB6下

#19


请关注

#20


哈哈,原来都没有解决。

#21


to  yesry(噎死你):不知你有何高见

#22


换在BCB5下应该没问题

#23


楼主:
我对ljianq(泉深水清) 先生的例子进行了测试,应用层没有问题.客户层我做了如下修改,
在BCB6中测试没问题.改动如下:
    ITest11ServerDisp V;
    V.Bind(LPDISPATCH(DCOMConnection1->AppServer)) ;
    try
    {
        try
        {
            TVariant tr;
            if( V->QueryData(tr) == S_OK )
            {
                ClientDataSet1->Data = tr;
                ShowMessage("数据取得成功!");
            }
            else
            {
               ShowMessage("数据取得失败");
            }
        }
        catch ( ... )
        {
            ShowMessage("远程调用失败");
        }
    }
    __finally
    {
        V.Unbind( );
    }

#24


bcb6和bcb5的区别实在是。。。?

#25


请继续gz

#26


呵呵, Cuiyc(阿昌)兄请问你测试了数据的更新提交吗?在查询模式式下BCB6.0没有问题,可是提交数据更新时问题却来了,如果你有好解决方案能共享吗?

#27


好像在bcb 6中对OleVariant不能修改,但是在DataSetProvide中的更新Update中为什么有OleVariant变量,它又是处理的?请各位大侠能否提供参考意见