服务器端代码如下,客户端调用GetData取得数据,调用GetNextData取得下一笔数据,第一次调用没问题,但过一段时间后,再次调用这两个方法时都会出错,报告“分布式事务已完成。请将此会话登记到新事务或null事务中。”服务器端mts DataModulefunction TrdmPhysic.GetData(const Condition: WideString): OleVariant;
var
  SqlStr: string;
begin
  if Condition <> '' then
    SqlStr := 'SELECT TOP ' + IntToStr(PacketRecords) + ' * FROM Physic WHERE '
      + Condition + ' ORDER BY PhyCode'
  else
    SqlStr :=
      'SELECT * FROM Physic WHERE PhyCode>(SELECT MAX(PhyCode) FROM Physic)';
  try
    if adsPhysic.Active then
      adsPhysic.Active := False;
    adsPhysic.CommandText := SqlStr;
    adsPhysic.Active := True;
    Result := dspPhysic.Data;
  except
    RaiseDataSetOpenErr(SqlStr);
    Result := VarNull;
  end;
end;function TrdmPhysic.GetNextData(const Condition: WideString;
  KeyValue: OleVariant): OleVariant;
var
  SqlStr: string;
begin
  if Condition <> '' then
    SqlStr := 'SELECT TOP ' + IntToStr(PacketRecords) + ' * FROM Physic WHERE '
      + Condition + ' AND PhyCode>' + KeyValue
  else
    SqlStr := 'SELECT TOP ' + IntToStr(PacketRecords) + ' * FROM Physic WHERE '
      + 'PhyCode>' + KeyValue;
  try
    if adsPhysic.Active then
      adsPhysic.Active := False;
    adsPhysic.CommandText := SqlStr;
    adsPhysic.Active := True;
    Result := dspPhysic.Data;
  except
    //RaiseDataSetOpenErr(SqlStr);//引发异常,返回sql语句
    raise;//一段时间后报“分布式事务已完成。请将此会话登记到新事务或null事务中。”
    Result := VarNull;
  end;
end;procedure TrdmPhysic.MtsDataModuleCreate(Sender: TObject);
begin
//  acPHYMIS.Connected := True;加不加这句代码都一样
end;procedure TrdmPhysic.MtsDataModuleDestroy(Sender: TObject);
begin
//  acPHYMIS.Connected := False;加不加都一样
end;procedure TrdmPhysic.acPHYMISBeforeConnect(Sender: TObject);
begin
   acPHYMIS.ConnectionString := GetADOConnectionString;//取得连接字符串的设置
end;initialization
  TComponentFactory.Create(ComServer, TrdmPhysic,
    Class_rdmPhysic, ciMultiInstance, tmApartment);
end.为什么会这样,神哪,救救我吧!

解决方案 »

  1.   

    估计是你的com+事务没有设置正确,如果设置了需要事务,则在程序里面需要显是写
    setComplute或者Setabort
      

  2.   

    同意楼上,一定要写setComplute或者Setabort,否则会错
      

  3.   

    如楼上两位所言了,只是搞不懂,查询也会启动事务么,可能是mts的事务吧
      

  4.   

    只要你的组件是需要事务的,从组件被创建的时候,事务(COM+的事务)就已经开始了。
    你可以将查询放在一个组件里,设置为支持事务,可是如果别的需要事务的组件调用了这个组件,会传一个事务Context(好像这么叫)进来,同样需要setComplute或者Setabort,所以还是都写上为好。
      

  5.   

    以前一个朋友做时,查询做成单独的MTS,并且选择支持事务查询与更新是分开的,更新当然要启动事务对象越小就控制越精确,比如,某些财务部不允许更新,而前台操作人员只可以录入,只有集成了WINDOWS安全性的COM/COM+才可以做到,否则,你用Socket联就可以了不要做成巨大对象
      

  6.   

    建议查询用的com+不要设成需要事务,浪费资源啊
    李维先生不是给我们建议了吗?笑天 
    说说你的架构啊
      

  7.   

    DJ_KK(蓝色代码) Corba更复杂啊!
      

  8.   

    procedure TrdmPhysic.MtsDataModuleCreate(Sender: TObject);
    begin
    //  acPHYMIS.Connected := True;加不加这句代码都一样
    end;procedure TrdmPhysic.MtsDataModuleDestroy(Sender: TObject);
    begin
    //  acPHYMIS.Connected := False;加不加都一样
    end;
    /////////////////////////////////////////////不一样!!!!!!
    你应该将acPHYMIS.Connected 属性在onactive中激活,在ondeactive中关闭
    个人意见
      

  9.   

    myling(阿德) 我是指在测试这个问题时加不加那行代码都是一样的效果你的意见很正确,我也是这么处理的,否则mts的事务处理会有点问题
      

  10.   

    还有一个问题,以前有兄北问过在midas的三层中,客户端不调用ClientDataSet的ApplyUpdate方法,而是调用服务器上自定义的更新方法,服务器如何将错误信息反馈给客户端处理?
      

  11.   

    在方法里面增加一个变参就可以了。
    在类型库编辑器中,新增一个参数,假同名称为sErrorInfo,类型为选择BSTR,然后自己在BSTR后面加上一个“*“号,然后双击和该参数同一行的最后一列,勾上”Out“