我在WebSanp的WebSnapPageModule 中通过 DComConnecion 和 SocketConnection 访问远程数据库都没有问题。但将DCOMConnection/SocketConnection 放在一公用的数据模块WebSnapDataModule中,之后各PageModule的ClientDataSet引用此DCOMConnection/SocketConnection ,设计期间可获得数据,运行期间:
  DCOMConnection 的情况下,报: 错误的O/S版本。
  SocketConnection的情况下,报:不接受的错误返回值(Excepted return value not received)。
  
  是何原因,百思不得其解,请高手指点一二!

解决方案 »

  1.   

    此问题可能是由于 WebSnap 对页模块的访问是多线程的缘故。解决方法:
    1。在编译之前,将所有 ClientDataSet 的RemoteServer 属性清空
    2。在页模块的激活事件中,设置 ClientDataSet 的 RemoteServer 属性
      

  2.   

    按你说的
    我定义一个function 变量,用FindModuleClass返回放置DCOMConnection/SocketConnection的DataModule,然后在Active事件中,动态将该DataModule中的DCCOMConnection/SocketConnection 赋给ClientDataSet的RemoteServer
     没戏,还是原来的现象。
      

  3.   

    相关源码如下,其中uDMdbProvider是放DCOMConnection的WebSnapDataModule单元,对象名为TwdmdbProvider,DCOMConnection已处于打开状态:unit uwsTest052602;interfaceuses
      SysUtils, Classes, HTTPApp, WebModu, HTTPProd, CompProd, PagItems,
      SiteProd, MidItems, WebForm, WebComp, WebAdapt, DBAdapt, DB, DBClient,
      MConnect, SConnect,uDMdbProvider;
    type
      TTest052602 = class(TWebPageModule)
        cdsCustomer: TClientDataSet;
        .......
      end;
      function Test052602: TTest052602;
      function wdmdbProvider: TwdmdbProvider;implementation{$R *.dfm}  {*.html}
    ......
    function wdmdbProvider: TwdmdbProvider;
    begin
      Result := TwdmdbProvider(WebContext.FindModuleClass(TwdmdbProvider));
    end;procedure TTest052602.WebPageModuleActivate(Sender: TObject);
    begin
      cdsCustomer.RemoteServer := wdmdbProvider.DCOM;
      cdsCustomer.ProviderName := 'dspTemp';
    end;
    ......
    initialization
      if WebRequestHandler <> nil then
        WebRequestHandler.AddWebModuleFactory(TWebPageModuleFactory.Create(TTest052602, TWebPageInfo.Create([wpPublished {, wpLoginRequired}], '.html'), crOnDemand, caDestroy));end.
      

  4.   

    呵呵,具体的俺也不大清楚,不过俺做了一个跟你一样的东东,主要是数据库的原因,在DCOM中的原因。或者你是做成ISAPI的话,很多原因是说不清楚的,也没有资料好查。
    你还是做成COM+吧,很方便的
    我做了一个是可以的,但是,好象动态查询不行,每一次查询的结果要么跟上次一样,数据没有发生变化,要么没有数据。
      

  5.   

    从上面代码看不出什么问题。
    再提醒你几点:
    1) 函数:function wdmdbProvider: TwdmdbProvider;在 uDMdbProvider 模块中已经有了,不需要在这里写。不过这不是产生问题的原因。
    2) uDMdbProvider 模块中 initialization 部分,
      if WebRequestHandler <> nil then
        WebRequestHandler.AddWebModuleFactory(TWebDataModuleFactory.Create(TwdmdbProvider, crOnDemand, caDestroy)); //一定要用 caDestroy,这很关键!!
    3) DCOM 不需要处于打开状态(因为每次都会 Destroy)
    4) 保证所有模块中使用这个DCOM 的 ClientDataSet 的 RemoteServer 属性都清空。很重要!你再试试,应当可以的(我用的是 SocketConnection,但估计原理是一样的)
      

  6.   

    to jacketxu(草鞋):
     >> 好象动态查询不行,每一次查询的结果要么跟上次一样,数据没有发生变化,要么没有数据。
     
        不会的。除非你用 caCache 建立的数据(或页)模块。但即使是用 caCache,也是可以解的,即在 BeforeDispatchPage 之前,将数据集先关闭,再打开(也就是刷新啰),一点问题都没有。
        WebSnap 虽然有许多不足,但也有其优越的地方。
      

  7.   

    谢谢你的提示,按你给的方法,我发现了以下一个很有意思的现象:
      SocketConnection和DCOMConnection在WebSnap是不同的:如果用SocketConnection,
        TwdmdbProvider应设为crOnDemand, caDestroy
      如果用DCOMConnection 
         TwdmdbProvider可是crOnDemand, caDestroy 也可是 crOnDemand, caCache   为什么不能是Always 的原因我还不太清楚,但这里面还有一个相关问题:
         虽然我在ApplicationModule中已做了OLEinitialize,但若直接放置一个DCOMConnection就会发生错误提示"标记没有引用存储"。这时如果放置一个ADOConnection的话(虽然没让它干什么),错误就不会发生了。
         所以我怀疑是因为在OnDemand 之前要做一些环境初始化的工作(具体是什么不知道),而always的模块会在这些初始化工作之前被创建,所以会出错。 
         另外,把 TwdmdbProvider设为Destroy我任为是不妥的(虽然目前看SocketConnection不得不这样做),因为把远程联结放在DataModule中的目的就是为了共享连接,如果这个DataModule总是处于不断的Create - Destroy中,这种共享的意义就不大了。因为连接本身是要占用一定时间的。随便说一下,
      虽然SocketConnection的连接速度比DCOMConnection快,但SocketConnection的数据传输速度确比DCOMConnection慢,如果是同一台机器做远程数据提供者和使用者,这个差距可能不太明显,
      但若是不同的机器这个差距就明显得多了。
      

  8.   

    to jacketxu(草鞋),
      动态查询的问题,我同意hiflower(花),不是DCOM的问题。DCOM中的远程数据模块是无状态对象,为会为你保留上回的操作参数的。一定是你自已没有在WebSnap端刷新远程调用(重新请求数据)。
      

  9.   

    我认为,
    这里的共享连接应该是在同一个线程内部才允许,当WEB页提交一个请求时,连接模块只激活一次,各个模块就可以共享这个连接了。当再次提交一个请求时,又会产生另一个线程,它不能使用上一次提交时的那个线程的连接,因此,如果是 Cache 的话,就会出问题了。如果要多个线程共享连接,大概要用到连接池之类的东西了吧,我不太懂。
      

  10.   

    楼上的解释有些不通。因为DCOMConnection模式,是可以设为Cache的。
    另外我发现WebSnap好象是单线程的,即一个对象,同时只有一个实例。如果实例不Destroy的话,实例中所建的连接DCOM的线程,也是存在的(除非你主动关闭它)。在Cache模式下,就算是一个新的Web请求,也是相同的对象实例来服务它,固线程也还是原来的线程。
        ----- 当然,这样的推断也不是严谨的。我只是想找到一种合理的解释吧了。
       这贴的问题已解决,就此结贴。若有兴趣,希望可以继续讨论!