平生做的第一个三层程序:
服务器端:1个DataSetProvider,1个adoquery
客户端:1个dcomconnection,一个clientdataset
将所有的数据连接设置好后(没有一句代码),连接成功,
但现在我想改变clientdataset连接的表,使用以下语句:
clientdataset.close;
clientdataset.commendtext:='select * from table';
clientdataset.open;
提示:can not perform this operation on an open dataset!
请高手指点!

解决方案 »

  1.   

    应用服务器的编写:
    (1)新建一个工程
    (2)点击“File”“New”“Other”,选择Multiter页标签的Remote Data Module
    (3)设置CoClassName(例:输入TestServer),点击OK就会进入Remote Data Module编辑框
    (4)在编辑框中可以添加任何与数据库相连的组件,既然你的机器上装了sql server ,你就可以 添加一个ADOConnection和ADOTable,进行数据库的连接设置。这里我要提醒一句,就是在用ADOConnection连接数据库的时候,最好把登陆数据库的密码保存下来,并且ADOTable1.active不要设置为True!!!然后再添加一个DataSetProvider1(在Data Access页中),并将其DataSet设置为TADOTable1.
    (5)编译运行此程序,就算注册了
    客户端的编写:
    (1)新建一个工程文件
    (2)在其中添加SocketConnection1(在DataSnap页中),将它的Host设置为你的应用服务器所在的机器名,在ServerName的下拉列表框中选择应用服务器的名称,port默认为211(注意:TSocketConnection靠的是TCP/IP协议进行通讯,所以要在应用服务器端需额外运行Scktsrvr.exe程序,该程序在..\\Borland\Delphi6\Bin目录里)
    (3)然后添加一个ClientDataSet1(在Data Access中),将其RemoteServer设置为SocketConnection1,将PorviderName设置为DataSetProvider1,
    (4)再添加一个DataSouce1和一个DbGrid1,将DataSouce1.DataSet设置为ClientDataSet1,DBGrid1.DataSource设置为DataSource1
    (5)在FormCreate中编写代码如下:
      procedure TForm1.FormCreate(Sender:TObject);
      begin
          SocketConnection1.Connected:=True;
          ClientDataSet1.Active:=True;
      end;
    (6)编译运行,你的客户端就可以读取Sql Server数据库中的数据了!
      

  2.   

    谢谢SmallHand(火龍) 以上的功能我已经基本实现了,现在的问题是如何实时读取其他表内容
      

  3.   

    自已看了一下csdn 中的一些例子,好像不好用commandtext来更换表,但不知如何更换操作表,请高手帮忙!!!
      

  4.   

    是你的DataSetProvider1设置有问题,将DataSetProvider1的options属性设置为[poallowcommandtext]
      

  5.   

    谢谢 wslashy(微笑的星) ,不过我这个参数已经设置了
      

  6.   

    是的 CommandText 违反的三层的逻辑,非常不赞成使用CommandText 好像不是用 Open, 是用 Execute
      

  7.   

    问 comanche(太可怕) 你有什么好的方法吗
      

  8.   

    一、首先在DataSetProvider1的OnDataRequest事件里写如下代码:function TContractServer.DataSetProvider1DataRequest(Sender: TObject;
      Input: OleVariant): OleVariant;
    begin
        with ADOQuery1 do
        begin
            Close;
            sql.Clear;
            sql.Add(input);
            open;
        end;
        result:=DataSetProvider1.Data;
    end;二、在客户端写如下语句:
    procedure Tform1.FormCreate(Sender: TObject);
      ClientDataSet1.close;
      ClientDataSet1.data:=ClientDataSet.DataRequest('select * from table');
      ClientDataSet.Active:=True;   
    end;当然这里的Clinetdataset1与服务端的DataSetProvider1是相连的。 
      

  9.   

    楼上的兄弟,这个方法是在 d5之前,没有 CommandText 时广泛采用的一个方法呵, 实际上还是 CommandText关于怎样避免 CommandText 这要从服务器设计方法说起服务器应该对客户机的所有要求都有个提供者(也以说是逻辑,这个提供者不当指 DataSetProvider), 这样就不会出现你这种情况. 想换内容就改个 ProviderName,不过这仍是不赞成作法, 没理由有这种情况出现,一个 cds 对一个 DataSetProvider最好
      

  10.   

    如果你真的很想这么用,另外提供个方法这个 cds 根本就不连 DataSetProvider, 因为这个不是一一对应关系在服务器作个COM 方法cds.Data := Connection.AppServer.Method(params...);服务器这边function method... :OleVariant;
    begin
      result := xxxProvider.Data;
    end;
      

  11.   

    用xiaoyan21(明月心) 的试试了一下,可以
    comanche(太可怕) 你这个能举个例子吗
      

  12.   

    comanche(太可怕) 简直是在瞎扯.
      

  13.   

    xiaoyan21(明月心)的方法是手动取得数据最常用的方法.并非如comanche(太可怕)所说用在D5以前.我不知道comanche(太可怕) 有没有真正做过三层结构,要知道D5以后的MIDAS是无状态的,而在D5以前在有状态的.要实现楼主的要求改变多个表的连接,xiaoyan21(明月心)的方法完全可用.
      

  14.   

    指正一个, d5 以后的RDM仍是有状态无状态并存的,d5 和 d4 的最大区别在于 Provider 和 DataSetProvider, Provider 是要 export to type library(成为 type library 的一个属性), 而 DataSetProvider 不要,但这样牺牲了性能代价, 在IAppServer 的所有方法中都加入了 ProviderName :WideString; 这个被用作到列表中查找正确的 DataSetProvider, d4 以前是不需要的。关于是否有状态 d5, d6, d7 都是不一定的,跟设计关系很大,比方客户端 cds.PacketRecords 设定不为 -1 时, 服务器这时是有状态的,这就需要在 DataSetProvider->AfterGetRecords 加一句 DataSet.Close 保持无状态。还有一种可能就是 master/detail 时,detail 表总是会在取完数据后是 active, 这样服务器又是有状态,也需要在取完数据后 设所有表 active->false我还坚持说 明月心的方法就是 CommandText, 这是在 d5 以前的作法,因为这之前没有CommandText 支持, 这样并没有很好封装业务规则.