在编写分布式应用系统时,书上都是这么说的: 在远程应用服务器的远程数据模块中,加入TDCOMConnection、TDataSet、TDataSetProvider连接数据库取出需要的数据,在客户端放一个TClientDataSet从应用服务器中取得数据,然后再通过赋值给界面上控件来显示。但如果以OO原则,从企业逻辑付封装在企业对象中,客户端再通过这个企业对象从数据库取出数据。
我想问的是:
1、应用服务器中如何定义什企业对象,如何把TDataSet、TDataSetProvider封装起来,又是如何暴露给客户端的?
2、客户端又是如何取得企业对象,并调用基方法的???如果以查询MIS中客户列表为例,应该如何设计与实现???先谢了
我想问的是:
1、应用服务器中如何定义什企业对象,如何把TDataSet、TDataSetProvider封装起来,又是如何暴露给客户端的?
2、客户端又是如何取得企业对象,并调用基方法的???如果以查询MIS中客户列表为例,应该如何设计与实现???先谢了
解决方案 »
- DELPHIWORD文档处理问题解决
- Delphi7.0 怎样设置 打开程序主窗体之后 自动 弹出登录窗体
- DELPHI的问题
- 找Delphi兼职开发人员
- 超高难度的简单问题,我愿200分求解.◆◆◆◆◆
- 急急!!在线等待!!水晶报表中如何按每5条记录自动分组阿??????小弟穷阿。。帮帮忙阿
- delphi中怎样打开一个html文件
- 为什么这样插不了Jpeg格式的图片到数据库中
- 怎么用dbgrid中的picklist建立下拉选择框??求助啊!!
- 用ADO时,如何使用Cache?
- 请问如何实现 delphi6 自带的 quickreport 将打印的每一页转成 BITMAP 图型格式 ??????
- 如何获取sql数据库的备份目录?
1、如果你要客户端连获取这个数据的步骤:
应用程序服务器的远程书记模块上:加一个TQuery(加其它的比如TAdoquery也可以),该控件的SqL语句为select * from 客户列表,当然连接到数据库的连接设置也要设,再加一个TDataSetProvider,其数据集指向前面的Tquery.编译运行一下!
客户端:加一个TDCOMConnection,并连接到前面的应用程序服务器,加一个TClientDataSet的Privder属性指向提供者,这时打开数据集TClientDataSet就可以获取数据,加TDatasource指向TClientDataSet,加DBGrid执向TDatasource就可以显示数据了。
以下为示意图,<->表示调用和返回:
ClientDataSet
<-> RemoteConnection
<-> IAppServer
<-> Provider
<-> Resolver & DataAccess Component
其中IAppServer,由应用服务器程序的TRemoteDataModule对象来实现,
ClientDataSet发出IAppServer接口提供的方法的调用,然后RemoteConnection
处理客户端和应用服务器端的通讯,把这个请求转发给IAppServer,IAppServer
再根据ProviderName参数,选择合适的Provider对象,然后将请求实际发给Provider对象
Provider有DataSetProvider,我只用过DataSetProvider,姑且以它说明,
每当Provider对象放在TRemoteDataModule上面时,它通过IProviderContainer接口向
TRemoteDataModule注册,声明自己是一个Provider对象实际上我们可以吧Provider也看作一个接口,它具有和IAppServer接口差不多的接口,
但是它不直接向外披露自己打开Midas.pas和Provider单元比较一下就知道这是IAppServer接口的声明, ClientDataSet正是调用这些方法请求读写数据的: IAppServer = interface(IDispatch)
['{1AEFCC20-7A24-11D2-98B0-C69BEB4B5B6D}']
function AS_ApplyUpdates(const ProviderName: WideString; Delta: OleVariant;
MaxErrors: Integer; out ErrorCount: Integer; var OwnerData: OleVariant): OleVariant; safecall;
function AS_GetRecords(const ProviderName: WideString; Count: Integer; out RecsOut: Integer;
Options: Integer; const CommandText: WideString;
var Params: OleVariant; var OwnerData: OleVariant): OleVariant; safecall;
function AS_DataRequest(const ProviderName: WideString; Data: OleVariant): OleVariant; safecall;
function AS_GetProviderNames: OleVariant; safecall;
function AS_GetParams(const ProviderName: WideString; var OwnerData: OleVariant): OleVariant; safecall;
function AS_RowRequest(const ProviderName: WideString; Row: OleVariant; RequestType: Integer;
var OwnerData: OleVariant): OleVariant; safecall;
procedure AS_Execute(const ProviderName: WideString; const CommandText: WideString;
var Params: OleVariant; var OwnerData: OleVariant); safecall;
end;
Provider不直接处理请求,它也转发请求给Resolver,对于TDataSetProvider的Resolver来说,Resolver有两种,
一种时DataSetResolver,一种是SQLResolverTDataSetProvider对象有两个属性,DataSet, ResolverToDataSet
根据ResolverToDataSet属性决定TDataSetProvider使用何种ResolverDataSetResolver则是完全由Provider的DataSet属性所指向的DataSet来处理,
比如取数据时,它就打开这个DataSet,
更新的时候就移到合适的位置,然后Edit,Post,依靠这个DataSet本身的来处理
数据请求,你可以在这个DataSet上面设置一些事件来控制数据的读写,就像CS
程序一样,当TDataSetProvider.ResolveToDataSet为True时,使用这种Resolver,
这时候要求DataSet完全实现IProviderSupport接口SQLResolver是这样一种Resolver对象,它根据请求自动产生合适
的SQL语句发送到数据库后台来读取或更新数据,它需要DataSet的IProviderSupport
接口来获得一些元数据(比如表名、字段名等)来产生合适的数据,并最后
通过DataSet的IProviderSupport接口将SQL提交到数据库后台,TDataSetProvider
默认使用这种Resolver不论何种Resolver,都必须根据TDataSetProvider.DataSet这个属性来工作
并且这个DataSet必须实际支持IProviderSupport接口,虽然TDataSet这个基类
本身声明了IProviderSupport支持,实际上它并没有有用的IProviderSupport实现至于如何披露企业对象给客户端,主要是通过Provider名称,IAppServer有个AS_GetProviderNames
方法,ClientDataSet一旦确定了RemoteServer以后,它就可以通过RemoteConnection请求IAppServer
返回它所披露的Provider列表了我理解是这样,企业对象和Provider还是有层次上的差别,Provider着重于数据处理,
提供一个数据访问接口,而企业对象可能有数据处理,但是它超越了数据处理,它有更高级的方法,
它面向更高级的访问者,而Provider只有ApplyUpdates,XXXRequest,Execute这样的数据处理接口,没有那么灵活,但是要处理象你的"以查询MIS中客户列表"的问题,DataSnap的方案还是挺便利的,方法前面回复人: hawksoft(明月清风) ( ) 信誉:105 已经举例说明了,很简单是吧至于ClientDataSet如何具体访问IAppServer的,最好还是参看源码,其实不甚了解也是可以的,
只要知道它是这样工作的,知道它有一个RemoteServer属性,而这个RemoteServer对象有一个
IAppServer,所有的数据请求最后转化到指定的Provider上就可以了说了这么多,好像言不及意,但实际上你明白这些原理,就很容易把握应该做怎样利用DataSnap作应用服务器
你们误解了我的意思。 关于DataSnap的机制,我略懂一二,也知道如何用TSqlConnection/DataSet/DataProvider/DComConnection/ClientDataSet/DBGrid等组件显示和修改数据。 我是想了解如何使OO的设计思想在应用程序服务器加入企业对象,然后再披露这些企业对给客户端,客户端通调用这些企业对象中方法来获得数据及更新数据。 还是以查询客户列表为例,看了一些关于分布式系统的书,我的理解是: 在应用程序服务器中定义一个对象TPortfolio,其中有方法GetCustomers,这个方法封装了DataSet、DataSetProvider向客户端提供客户列表的数据集。 在客户端通过 Var aPortfolio:TPortfolio ; aPortfolio.GetCustomers来获得数据。。 不知我这样理解OO应用在企业解决方案,是否正确???如果这办法是可行的,那么客户端如何取得应用服务器的企业对象及其方法?
var
Portfolio: IPortfolio;
Obj: OleVariant;
Data: OleVariant;Obj := ClientDataSet.AppServer.AS_DataRequest('$CMD$CreatePortfolio', YourParams);
Portfolio := IDispatch(Obj) as IPortfolio;Data := Portfolio.GetCustomers();应用服务器截获这个请求返回一个IPortfolio接口不过我以前做多层一直都是直接用ClientDataSet取数据的,很少再定一个假对象,觉得没什么大用
现时大多数中小型软件公司或企业都是用这种方案开发应用系统吗???
Obj := ClientDataSet.AppServer.AS_DataRequest('$CMD$CreatePortfolio', YourParams); 这个不明,请帮忙解释thanks
aPortfolio = TPortfolio.create;采用aPortfolio.GetCustomers调用来达到目的,是不可能的,因为你实例化的是本地类,不是远程应用服务器上的类。在三层种,客户端跟应用服务器只能通过远程调用来实现,是无法保留类的调用状态的,如果你想通过远程调用你应用服务器上的TPortfolio类的方法GetCustomers,你必须定义一个从IAppserver继承的接口IPortfolio,该接口包含GetCustomers方法,你的类方法必须实现该接口,同时因为远程服务其实是一种COM服务,所以你还必须实现Com服务接口。具体的你可以参看Delphi为你自动实现的接口,一般是你的远程数据仓库名前面加一个I字母。在服务器端为客户端定义类其实是没有意义的。所以一般情况下你直接在Delphi自动为你生成的接口下,添加新的方法,Delpi会在该接口的实现类,也就是你的远程数据仓库窗体里面实现该方法,你直接在客户端通过连接(SocketConnect,DCOMConnect等)对象的AppServer接口来调用GetCustomers方法就行了。但需要注意的是,通过这种增加接口方法来调用的方式是有限的,你的返回值是有限的,如果你想返回数据集,对象是不行的(如果高手说可以,请指教),我觉得如果你采用Delphi的这种三层模式,还是需要按alphax(无之心) 说得那样,利用ClientDataset返回数据集。如果你一定要这样做,建议你采用WebServices来进行。
下面是我理解得Delphi三层结构中,客户端调用服务器方法得过程:
1、客户端打开连接(SocketConnect,DCOMConnect,HttpConnect)
2、如果是是使用SocketConnect连接,则首先连接服务器的scktsrvr程序(Borland自带),由改程序调用连接指定的Com服务,如果该服务没有实例化,则创建COM对象,启动服务。DCOMConnect连接则由Windows自带的DCOM服务自己管理,HttpConnect连接需要通过Borland自带的一个dll来处理。
3、客户端发送的调用方法指令GetCustomers,则启动代理服务程序(COM服务,scktsrvr等)向你实际的应用服务器发出调用指令,并由代理程序把结果返回给客户端。
当然Delphi提供的这种三层在开发上确实比较快,但灵活性还是比较欠缺,所以现在做三层,我比较倾向于WebServices技术。它的灵活性和通用性都要好!如果你中间层用Webservices,客户端可以采用支持Webservices调用的任何语言开发。好处当然不只这一点,有兴趣可以看看!
具体这种方式能不能返回对象(包括数据集对象),我没试过。
具体这种方式能不能返回对象(包括数据集对象),我没试过。