在一个方法中,我准备多次修改DM.cds.CommandText属性来取参数值,DM.cds.Close;
DM.cds.CommandText := '...';
DM.cds.Open;
sName := DM.cds.Fields[0].AsString;...
...但当我第二次调用时,
DM.cds.Close;
DM.cds.CommandText := '...';
DM.cds.Open;//调试时系统执行到这一步就愣住了,半天才报个错“分步式事务已完
            //成,请将此会话登记到新事务或NULL事务中”如果屏蔽掉第二次调用的三句代码,程序运行正常,痛苦啊!
(注:几次的SQL均在SQL Server中测试通过)

解决方案 »

  1.   

    解决方法:1.不要使用commandtext
    2.中间层设置does not support transactions或设置成别的事务方式再试一下!根据你的需要,再决定,这应该是因为事务处理的原因造成的!
      

  2.   

    使用commandtext为的是根据动态组织的SQL取值does not support transactions肯定不行,我设的是需要事务,有更新操作。上面的只是一段程序片断
      

  3.   

    另外你确定你的SQL没问题吗?如果SQL本身通不过,好象也会出这样的错!!
      

  4.   

    SQL本身没事,但执行得太慢
    'SELECT TOP 1 FID FROM tGroup WHERE FClass=2 AND SUBSTRING(FCode,1,4)='0006'目的是要判段在tGroup表中存不存在满足WHERE条件的记录,这句执行的太慢了,导致事务超时,可能也有DM.cds一开一闭更改CommandText的原因,但我到SQL Server中运行第一次也比较慢,
    要达到这种目的SQL的SELECT部分还应该怎么优化?但我总觉得不是SQL本身的事
    怎样设定COM+事务超时?
      

  5.   


    是不是公用cds连接组件有什么限制啊,比如说要进行什么初始化之类,欢迎各高手参与讨论
      

  6.   

    SELECT TOP 1 FID FROM tGroup WHERE FClass=2 AND SUBSTRING(FCode,1,4)='0006'这个命令不科学,SUBSTRING指令无法利用索引,要判断记录是否符合调剂就必须进行TableScan,严重耗时。从参数来看,应该是判断前四个字符是否为0006,那么SQL更改为SELECT TOP 1 FID FROM tGroup WHERE FClass=2 AND FCode like '0006%'即可有效利用FCode字段上的索引,大幅度提高效率,缩短执行时间。试一下,Good Luck!
      

  7.   


    多谢楼上几位的关注,但问题还没有解决,我也按照Miracle所说的优化了一下,但仍然出错,
    我设置
    ConnectionTimeout=1000;
    CacheSize = 1000;
    CommandTimeout = 1000;
    又在组件管理器覆盖了全局事超时,将其设为300,可还是不行
      

  8.   

    我在组件管理器-〉时间查看器-〉应用程序中发现如下事件
            类型  来源    分类   事件
            信息  MSDTC   CM     4156
            事件详细描述:
            字串信息: Session idle timeout over, tearing down the session。   那位高手能根据这个事件信息解决一下,提示中的Session时间指的是程序中的什么时间
      

  9.   

    该方法框架如下:
      try
        try
          DM.cds.Close;
          DM.cds.CommandText := ...;
          DM.cds.Open;
          ...
          OleCheck(ObjectContext.CreateInstance(Class_oneObj, IoneObj, iIoneObj));
          iIoneObj.ExecSQL('...');
          ...
          iIoneObj.ExecSQL('...');
          ...
          DM.cds.Close;
          DM.cds.CommandText := ...;
          DM.cds.Open;//这次调用的时候时间特别长,导致超时
          ...
          DM.cds.Close;
          DM.cds.CommandText := ...;
          DM.cds.Open;
          iIoneObj.ExecSQL('...');
          ...
          SetComplete;
        except
          SetAbort;
          raise;
        end;
      finally
        iIoneObj := nil;
        iItwoObj := nil;
      end;那位帮帮忙,很急啊
      

  10.   

    类似的问题我也碰到过,不过早解决了
      我认为还是组件问题。
      这里假设组件执行的是写操作(读操作一般不会碰到该问题),且是本机执行(如果组件执行在其他机器则一定要确保midas.dll在system32目录下),组件在Delphi中的属性不要设为调试状态,卸载并删除原组件dll,重新编译,安装,问题就会没有了。
      有问题再贴出来。
      

  11.   

    怎么可能是超时呢,SQL设置适当的话效率很高的,浏览几千万笔纪录几秒钟内就能完成,所以一般组件不会超时的。
      还有如果是组件之间调用的话也可能会出现这种问题,可以在第一个组件,即根事务创建者设置调试,同时打开其它组件相关单元,即可自动调试到其他组件中去。
      

  12.   

    shsunb(我怕来不及):
        我按你说的,取消了调试状态,把组件连同组件包一起删除了,并把服务器\客户端的所有编译生成文件删除,然后重新编译、安装,此时系统不报原来的错了,改为报:“超时已过期”,请指教
      

  13.   


    对了,我把我的环境说一下,两台机器,一台临时数据库服务器(同事的)(SQL Server/XP),我的(Win2000)作中间层服务器,客户端也在我机器上运行
      

  14.   

    超时已过期 的原因是我把ConnectionTimeout改小了的缘故,但改大后又出现原来的错误提示了
      

  15.   

    midas.dll两台电脑的system32下都应该有的!  如果还不可以,可能是数据库造成的了,建议你将跟踪到的最终数据库执行的sql语句在查询分析器中测试一下执行效率,然后写个简单的组件,只执行该sql语句对比一下效率。如果还找不出问题所在,建议你考虑重新设计数据库对应表的索引,组件端重新设计。
      

  16.   

    还要注意adocon的问题。你是一直连接着还是每次需要时再连接的?
    执行SQL最好用adoquery,然后将数据集赋给cds,让cds彻底与数据库断开连接
      

  17.   

    有问题很正常,关键是你自己能否有一套解决思路。
        看了你的代码,如果iIoneObj不能一次调用就释放的话,试试我改的:
    try
        try
          DM.cds.Close;
          DM.cds.CommandText := ...;
          DM.cds.Open;
          ...
          OleCheck(ObjectContext.CreateInstance(Class_oneObj, IoneObj, iIoneObj));
          iIoneObj.ExecSQL('...');
          ...
          iIoneObj.ExecSQL('...');      if iIoneObj <> nil then iIoneObj := nil;//我加的
          ...
          DM.cds.Close;
          DM.cds.CommandText := ...;
          DM.cds.Open;//这次调用的时候时间特别长,导致超时
          ...
          DM.cds.Close;
          DM.cds.CommandText := ...;
          DM.cds.Open;      OleCheck(ObjectContext.CreateInstance(Class_oneObj, IoneObj, iIoneObj));//我加的      iIoneObj.ExecSQL('...');
          if iIoneObj <> nil then iIoneObj := nil;//我加的      ...
          SetComplete;
        except
          SetAbort;
          raise;
        end;
      finally
        iIoneObj := nil;
        iItwoObj := nil;
      end;
      

  18.   

    超时已过期一般是发生在ADOConnection打开的时刻。你大概是通过机器名来访问SQLServer的吧?换用IP地址访问。这种问题在写C/S结构的程序的时候经常遇到,通过IP访问的速度要比通过机器名快得多(不需要进行名称解析和Windows安全性验证)
      

  19.   

    超时已过期 的原因是我把ConnectionTimeout改小了的缘故,但改大后又出现原来的错误提示了
    =======
    从描述上看很可能就是连接数据库失败的原因,ConnectionTimeout改小,就无法及时连接数据库,导致“超时已过期”;而改的足够大,数据库是能连上了,但分布式事务却已经被结束,此时出现另一个错误,就是“分步式事务已完成,请将此会话登记到新事务或NULL事务中”
      

  20.   

    问题解决了,是由于程序处理流程逻辑不合理原因造成的,我在这个方法中调用了另外一个对象的一个更新方法,该方法更新了执行超时SQL语句的记录,反过来我在当前方法中又取这条记录,导致SQL反应迟钝(可能前面的更新还没进行物理更新),今天心情特爽,功能已完成,现在正在优化这部分程序,
    敢问楼上几位都是在搞d/com+编程吗?现在这种搭配行情如何?我准备走人喽,不过得等到明年,答应老板的