再次请教微软专家和大虾们,关于三层模型的问题

horris 2001-10-25 02:19:14
我在http://www.csdn.net/expert/topic/338/338495.shtm中的问题得到的回答与我所期望的有所不同,我可能没有讲清楚我想要的是什么。问题并非描述具体的应用,而是自已对三层模型的一点空想性思考。现将该贴重写如下,有点烦人,呵呵:
>>这个问题也欢迎CSDN众高手讨论,100分啊
假设Presentation层的组件安装在PC上,Bussiness层的组件安装在App Server上,Data层的组件,主要是数据库安装在Data Server上,而PC,App Server,Data Server分别是网络上的三个不同物理结点,数据访问方法采用ADO。这是Windows DNA的典型应用之一吧?
现在的问题是,User service组件调用Bussiness组件,并请求Recordset指针作为输出参数,因为是远程调用,所以要Marshalling Recordset指针,这实际上引起在PC和App Server之间的网络数据传送。而Bussiness组件呢,又通过Data service组件才能获取数据,而且同样通过Recordset指针,而又引起在App Server和Data Server之间的网络数据传送。这样一次数据请求会造成两个网络传输回合,岂不很低效?
>>我关心的不是Marshalling,而是存在两个network trip:以我提的场景看,由于数据层借助业务层提取数据,而业务层访问数据层,数据要经过业务层,因此数据从数据层到业务层,这是一次网络传输;再由业务层到展示层,又一次网络传输。实际上业务层对数据不做处理,只是将展示层的请求转换为对数据层的请求,因此两个网络回合显然是多余的。让展示层直接存取数据层是不可行的,因为有业务规则要由业务层处理。已有的解决方案:1。把业务层与数据层放在一台机器,2。把业务层与展示层放在一台机器。这两种方案恐怕还有必要把两个层的组件放在一个线程公寓里。而且如果要求应用服务器与数据服务器分开的话,两种方案就都不可行了。业务层有无手段,可以让数据层直接传送数据给展示层?难道三层模型非得这么低效吗?
...全文
123 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
horris 2001-11-13
  • 打赏
  • 举报
回复
人气这么少啊
hz1101 2001-11-13
  • 打赏
  • 举报
回复
英文太多了
horris 2001-11-09
  • 打赏
  • 举报
回复
这几天又想了想这个问题,觉得似乎不存在两次网络传输的情况,因为问题中的情形只是传接口指针,而Recordset接口应是在引用时才会发生真正的数据传输。另外,在组件间传Recordset接口指针也不是很方便,因为涉及到对Recordset对象的属性如何设置。
最近在M$ 70-100认证的training kit中发现了与我的问题相关的技术--Remote Data Service。下面是Microsoft Data Access Components (MDAC)中的一段文字,应该是有权威性的。
RDS provides a client-side cursor engine for disconnected recordsets. It also provides a very efficient service for marshaling recordsets between computers, over either the Internet or an intranet. This means that a server application can generate a set of data and copy it to a client application, which can browse the data as if it were connected to the actual data store. RDS also provides a way to bind Recordset objects to data-bound controls, which can greatly simplify writing this type of client application.

RDS provides three components to help developers write applications: RDS.DataControl, RDSServer.DataFactory, and RDS.DataSpace. An RDS.DataControl object is used to bind data-bound ActiveX controls to Recordset objects. Client applications use RDS.DataControl to browse or modify a Recordset. RDSServer.DataFactory is essentially a generic business object for communicating with data sources. It contains no business rules or other application-specific logic.

The Recordset object itself is obtained in one of two ways. First, the Recordset object can be created implicitly by RDS.DataControl. Properties of RDS.DataControl are set that identify the data server and query to be used. When the Refresh method is called, an RDSServer.DataFactory object is used behind the scenes to create the Recordset object. Second, custom business objects that return disconnected recordsets can be defined. RDS.DataSpace objects are used to create client-side proxies to these business objects. The client-side proxy does whatever is necessary to communicate with the business object. Once the proxy has been created, the application can call whatever method returns a Recordset object; it then sets the Recordset property of RDS.DataControl.

This book exclusively endorses the second method. Middle-service business objects will use data objects to create ADO disconnected recordsets. These Recordset objects will be passed back to the presentation layer using RDS. Presentation-layer client applications will use RDS to bind the Recordset objects to data-bound controls.

In intranet scenarios, DCOM can be used to transfer Recordsets between client and server computers. In Internet scenarios, however, HTTP will normally be used. In this case, RDS provides services to manage the HTTP communication. An Internet Server API (ISAPI) extension, Advanced Data ISAPI (ADISAPI), is installed on the Web server. ADISAPI does the work required to handle requests for Recordsets from client-side business object proxies. It creates server-side objects, calls the methods required to generate the Recordset objects, and converts the data to an efficient form for transmission back to the client. ADISAPI and the business object proxies handle all details of actually transmitting the data via HTTP.
Hover 2001-10-31
  • 打赏
  • 举报
回复
g z
horris 2001-10-30
  • 打赏
  • 举报
回复
我想知道我这样做是否有效?是否真正避免了两次网络传输。也许DCOM会做我意料不到的事?请专家指教。
horris 2001-10-30
  • 打赏
  • 举报
回复
to XT2:
我不这么认为。通过IDataReceiver,数据传输只在Data server和client之间传输,而不会通过中间层中转。而且,我认为disconnect recordset仍可以在client端实现,因为这个属性可以在Recordset接口生成时指定。
wyzegg 2001-10-30
  • 打赏
  • 举报
回复
这个是好贴,学习学习
XT2 2001-10-30
  • 打赏
  • 举报
回复
Same data traffic, since you still have to push data back through methods of that interface, and worse in that IDataReciver is tightly bound between these tiers. You lost benefits of disconnect recordset.
horris 2001-10-30
  • 打赏
  • 举报
回复
我明白你的意思了,XT2,感谢你的思考。
微软专家是什么意见呢?
XT2 2001-10-30
  • 打赏
  • 举报
回复
oh, that's true, I read the code too quickly.

You are actually doing callback, which is pushing data back. You may use disconnected Recordset, but let server callback is not a good idea in distribute system, think about security, and firewall issue. Still you have to marshal a client interface to server.

Besides all these potential problems, I have make my points clear in previous posts, sending recordset back to client is not good design in most scenarios.
Designing three-tier or n-tier system there are many more concerns in addition to performance.



maple2001 2001-10-25
  • 打赏
  • 举报
回复
在涉及要将大量数据取到前台时(譬如打印工资单),这样应该能快很多吧!谢谢horris兄作答
horris 2001-10-25
  • 打赏
  • 举报
回复
假设业务层提供一接口方法,IBussiness::GetPresentationData(...,[out]IRecordset*);
展示层将调此方法获得数据。
数据层提供一接口方法,IDataService::GetBussinessData(...,[out]IRecordset*);
IBussiness::GetPresentationData(...,IRecordset* pIRecordset)
{
// implement some bussiness rules for converting presentaion request to database request
...
// then retrieve data via data service
pIDataService->GetBussinessData(...,pIRecordSet);
return S_OK;
}
这样,数据岂不是传了两次?一次从数据服务器到应用服务器,一次从应用服务器到客户机。

不过,XT2的回答有一点道理:

>>因此两个网络回合显然是多余的
>>让展示层直接存取数据层是不可行的,因为有业务规则有处理
>XT2:These two statements seems contradict, you already said that middle tier is necessary why two

roundtrip is not necessary?

>Even if your data can be sent directly to client, you should not do that, which incurrs another

impractical assumption: client can always handle the data sent by data tier directly.

>If you requiring a client to have data access capability, then the PRESENTATION tier's can be

renamed as presentation and data access tier.

不知以下解决方案是否能避免两个网络回合,只发生一次数据传输?

展示层提供一接口IDataReceiver,并有方法FillData([in]IRecordset*),则业务层修改为:
IBussiness::GetPresentationData(...,/*[in]*/IDataReceiver* pIDataReceiver)
{
// implement some bussiness rules for converting presentaion request to database request
...
// then retrieve data via data service
pIDataService->GetBussinessData(...,pIDataReceiver);
return S_OK;
}
数据层修改为:
IDataService::GetBussinessData(...,/*[in]*/IDataReceiver* pIDataReceiver)
{
// retrieve data to construct IRecordset
...
pIDataReceiver->FillData(pIRecordset);
// pIRecordset are pointer to IRecordset constructed on above
return S_OK;
}
展示层生成IDataReceiver,请求数据时,将此接口传给业务层:
pIBussiness->GetPresentationData(...,pIDataReceiver);

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧