假设业务层提供一接口方法,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);

解决方案 »

  1.   

    在涉及要将大量数据取到前台时(譬如打印工资单),这样应该能快很多吧!谢谢horris兄作答
      

  2.   

    我想知道我这样做是否有效?是否真正避免了两次网络传输。也许DCOM会做我意料不到的事?请专家指教。
      

  3.   

    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.
      

  4.   

    to XT2:
    我不这么认为。通过IDataReceiver,数据传输只在Data server和client之间传输,而不会通过中间层中转。而且,我认为disconnect recordset仍可以在client端实现,因为这个属性可以在Recordset接口生成时指定。
      

  5.   

    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.
      

  6.   

    这几天又想了想这个问题,觉得似乎不存在两次网络传输的情况,因为问题中的情形只是传接口指针,而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.