我目前在想一套架构,先给大家说一下思路,有几个问题请帮忙思考一下:数据库:SQLServer 2000
中间层:Com+,midas
客户端:用InfoPower 3000控件组中间层主要分2层:
1:企业对象,比如产品对象,人员对象,分别提供相应的接口方法给组织对象调用,主要负责数据的查询,更新等处理。2:组织对象:包括:查询组织对象(主要进行数据的查询,将结果通过接口以clientdataset.data的形式返回
给客户端的clientdataset)。更新组织对象(主要进行数据的更新处理,通过接口取得客户端clientadaset.delta,然后通过企业对象
提供的接口方法进行数据的更新)3:字典对象,主要负责对数据字典信息进行维护,要在数据库中建立字典表,保存字段,表的相关信息。客户端:
1:clientdataset不保存任何信息,只是通过:clientdataet.data:=datas(组织对象返回的数据包,取的数据)这样就有一个问题:clientdataset没有任何字段信息,所以displaylabel就是个问题,针对这个情况,我建立了一个数据字典对象,
通过它取得字段的相关信息,然后在运行期分别设定字段的相关信息。还有一个问题,因为我们的表不可能都是单表,很多数据可能有lookup字段的问题,这个问题我目前没有很好的解决,有一个思路:用过InfoPower的朋友可能知道,有一个组件叫wwDBLookUpcombo,我通过它类进行lookup字段的处理。然后还有lookup字段显示的问题,比如要将编号显示成名称:我是通过字段的Gettext事件进行处理的,这样就要知道字段的名称。然后写自
定义事件。问题1:这种架构是否可行?
问题2:如果客户端clientdataset不保存任何字段信息,是否有很多不方便的地方?
问题3:对于lookup字段是否有更好的解决办法?请大家帮忙讨论。谢谢!

解决方案 »

  1.   

    你相当与没有用Midas提供得许多强大得功能,这中结构给我得感觉老兄得是三层结构很清楚得结构,clientdataset不保存任何字段信息,这个是对得,但是你设计得时候可以先连接啊,连接后添加子段,然后把连接变成虚得(假得)但是CLientDataSet里会有这些子段得,这个思想和二层里建立临时表#Table,然后TQuery连接Table,但是在运行得时候是#Table,的思想差不多,关于Lookup的问题,李威在locate和lookup在多层的那本书讲了处理的方法,我就不写了。其实我们的一个原则就是能在客户段处理的东西不要放到COm+中。
      

  2.   

    问题1:这种架构是否可行?
    我认为是可行的。请问:是否每一个企业对象都继承自TMTSDataModule。
    问题2:如果客户端clientdataset不保存任何字段信息,是否有很多不方便的地方?
    开发当然不方便了,但同时带来的是通用性和易维护性。
    问题3:对于lookup字段是否有更好的解决办法?
    你如果使用wwDBLookUpcombo来实现Lookup,那么每次在打开主表的数据集时(即调用组织查询对象的方法获取数据),相应的LookupDataSet也要打开数据集(可以每次调用组织查询对象的方法获取数据,也可以一次调用常驻内存),不知你采用那一种解决方式。
    还有,在客户端程序设计期指定字段是不可避免的,尽量少指定就行了。
    我的几点愚见。
      

  3.   

    1.架构很不错,我的水平看不出什么来:)
    2.不便可能会有,不过是否这样独立性更强呢?MIDAS的不懂:)
    3.我的意见是:用视图。其实我更倾向于所有从数据库中读数据的操作都从视图中读出,视图相当于从物理字段到逻辑字段的一个转换层。你可以在视图中将数据库中的实际字段AS成字典字段;或者你也可以放到一个企业对象的组件中去,只不过是将来改SQL语句的时候在哪里改的问题。
      

  4.   

    笑天:
    查询组织对象和更新组织对象是每个企业对象对应一个查询和更新组织对象呢,还是按事务分成两个大的对象查询组织对象与更新组织对象?个人窃以为,如果一一对应的话,势必造成数量众多的对象,如果只是分成两个大的对象的话,那这个对象的可重用性及扩展性肯定会受影响。我的做法是是按事务分成两个大的对象查询组织对象与更新组织对象?在查询组织对象和更新组织对象中实现通用查询和通用修改,所谓的通用包括:单表的查询和修改,多表(包括1对N的主从表)的查询和修改,还要实现对客户端传递来的DELTA的SQL解析,
      

  5.   

    WangPeter(Peter)
    "是否每一个企业对象都继承自TMTSDataModule。"
    基本上是!'你如果使用wwDBLookUpcombo来实现Lookup,那么每次在打开主表的数据集时(即调用组织查询对象的方法获取数据),相应的LookupDataSet也要打开数据集(可以每次调用组织查询对象的方法获取数据,也可以一次调用常驻内存),不知你采用那一种解决方式。'视情况而定,基本上是长住内存的!"我听说用友U8系统有9000(九千)多个组件,不知是否吹N"
    我认为这个完全是有可能的笑天:
    5ierp(得道的猫)说的对!eastliangliang(青苹果)(道可道,非常道) 
    用视图的方便在于数据的显示,但是对于更新确实有不方便的地方!再说我想能够实现对字段的增加,以及diaplaylabel的动态设定.
    客户端基本上是很少保存字段信息的,当然不可避免的要写死一部分字段,比如lookup字段
      

  6.   

    我说的是用视图只做显示,更新时直接操作表。你是说不用delta进行更新?
      

  7.   

    ——“企业对象,比如产品对象,人员对象,分别提供相应的接口方法给组织对象调用,主要负责数据的查询,更新等处理。”——“是否每一个企业对象都继承自TMTSDataModule?基本上是!”每个企业对象的查询,更新处理的过程基本上都差不多吧? 那不是很多代码都是重复的?
      

  8.   

    企业对象都继承自TMTSDataModule,那么这些企业对象其实是“集合”对象。例如 产品对象其实是“产品集”。当利用 midas 时,查询和更新可以就利用 GetRecords 和 ApplyUpdates 两个方法解决。但是“现实中我们对某个业务对象有什么操作”,其实是对这个“集合”的某个元素或着子集的操作,那楼主准备怎么做呢? 是先对这个企业对象 的内部元素进行过滤,然后再进行操作吗?
      

  9.   

    很简单,infopower的wwdbgrid有selected属性,专门存储字段属性,我还有我的diy-infopower grid,超级功能,自定义窗体,自定义报表,自定义查询,自定义统计,超酷,多给点分我就发给你
      

  10.   

    flayyao(姚俊) 你要多少分没有问题啊mail:[email protected]
      

  11.   

    但是“现实中我们对某个业务对象有什么操作”,其实是对这个“集合”的某个元素或着子集的操作,那楼主准备怎么做呢? 是先对这个企业对象 的内部元素进行过滤,然后再进行操作吗?我们的理解好象不是一样我指的对对象的操作就是比如吧:
    一个员工对象,要更改该员工的职务,那么我们就 提供接口方法,
    update_title(per_id,tite_id) 当然现实中我们可能没有这种简单的操作,我只是打个比方我对你说的子集具体指什么不太明白,能否具体说明?
      

  12.   

    很简单,infopower的wwdbgrid有selected属性,专门存储字段属性,我还有我的diy-infopower grid,超级功能,自定义窗体,自定义报表,自定义查询,自定义统计,超酷,多给点分我就发给你selected属性的应用我已经研究过了
      

  13.   

    多层结构中,客户端所修改的数据都会暂存在本地缓存中,就是 TClientDataSet 的 Delta,然后可以一起提交中间层进行更新。楼主举的例子:
    一个员工对象,要更改该员工的职务,那么我们就 提供接口方法,
    update_title(per_id,tite_id) 那么这样的话,每更改一个员工的职务,就需要调用一次远程方法。我个人认为效率太低!
      

  14.   

    我所说的“子集”,举个例子:数据库中有个“员工表”包含了所有员工的信息。这个时候,我想把“所有职务为副经理的员工”全部提拔为“总经理”。  这里,“所有职务为副经理的员工”也就是我说的一个“子集”。那么楼主的“员工对象”该怎么设计呢? 是另外提供一个接口方法吗? 还是在循环中调用update_title(per_id,tite_id) 方法?又或是直接生成 sql 语句更新数据库呢?
      

  15.   

    架构是否合适要看它是不是符合你的项目的需求和业务逻辑。你最好把这两个问题描述清楚一些。
    至于对数据的更新操作,我觉得用服务接口调用的方法比较好。因为在客户眼中的一步完整操作,有可能不能用一条SQL实现,操作的可能不只一张表,对不同的表操作的记录数也不一样……,更重要的是,虽着项目的进展,你的业务模型有可能会发生变化,为了提高对变化的适应能力,应该把实现封装起来。不过,提供给远程调用的方法粒度不要过细,不要提供类似对一个对象的属性进行修改的方法,而应该通过分析你的需求,总结出在建立在业务层上的一组正交的相对完整、独立的操作的集合。
    关于对象的显示问题,我觉得如果使用数据控件显示数据集的方法很难适应需求的变化的,因为它把对象的外在表现形式和对象的内部结构直接耦合在一起了。当然,如果你的客户对显示形式要求不高的话也可以这样做,但把表现与结构分离会给你带来更大的灵活性。
      

  16.   

    那么这样的话,每更改一个员工的职务,就需要调用一次远程方法。我个人认为效率太低!我并不是说就要这样修改!我只是打个比方,当然实际中不会只是修改职务
    当让可以用as_applyupdate来更新
      

  17.   

    那么楼主的“员工对象”该怎么设计呢? 是另外提供一个接口方法吗? 还是在循环中调用update_title(per_id,tite_id) 方法?又或是直接生成 sql 语句更新数据库呢?一般情况下是用delta 来更新的
      

  18.   

    “架构是否合适要看它是不是符合你的项目的需求和业务逻辑。你最好把这两个问题描述清楚一些。”我的这个架构打算用到ERP项目中,具体的企业对象会很多。业务逻辑,主要是主细表的更新,以及对lookup字段的显示,当然还有更新问题,我们毕竟不能将”编码“显示给用户看吧。如果我们在服务器端将“名称”直接查询出来的话,对于数据更新会存在一定的不方便,我主要打算简单的调用as_applyupdate方法。“提供给远程调用的方法粒度不要过细,不要提供类似对一个对象的属性进行修改的方法”我没有打算提供过细的粒度,上面举的例子可能使大家产生误解了。我也不打算直接写SQL语句来更新。“关于对象的显示问题,我觉得如果使用数据控件显示数据集的方法很难适应需求的变化的,因为它把对象的外在表现形式和对象的内部结构直接耦合在一起了”对于这个问题,我目前只能写死在数据控件中,没有更好的方法,你是否有更好的建议呢?
    不如对需要lookup字段的显示。前提是我的clientdataset不打算保存任何信息,大部分属性是在运行期设定的,这主要是为了适应需求的变化
      

  19.   

    关于如何显示上问题,另一个论坛的一个贴子好象有点关系,大家可以去看一看,讨论讨论:
    http://www.chinaithr.com/bbs/bbs11/28.xml
      

  20.   

    这个帖子提到用data感知控件的缺点我不赞同!
    我们开发系统除了要考虑系统的延展性,开发效率也是我们要考虑的因素
      

  21.   

    一句话 
    如果不用数据感知控件 那么对数据的显示 最终还是要我们自己写 通过什么呢?用什么方法?vcl?最终的结果呢?--自己写一套数据感知控件!有区别吗?
      

  22.   

    看来研究COM+和MIDAS的人很多,但是认真看过微软DNA架构的人却很少。
    我现在开发的系统就是使用你所说的架构来编写的,也就是DNA架构。你的第一个问题,根本就不成问题!很简单,ClientDataSet本来就是动态的,你把他看成
    僵硬的与数据库一一对应,自然不能对付Lookup、Calculated字段。由于客户端的多样性,因此对于这部分逻辑,我们需要重建数据集!问题二:这种架构怎么不可行?我的系统虽然还没有完成,但对付多客户端根本没有感觉到速度问题,当然你必须使用COM+的对象池和连接池,仅当第一个客户登录时较慢,那是因为COM+组件JIT的问题,其后的客户使用起来跟两层速度上感觉没有差别。至于业务对象的分割,如果你不从OOAD开始,这样的讨论是毫无意义的。如果你用ROSE得出UML图,一切都很简单了,
    建议看看微软的DNA架构,你就会理解这些问题。
      

  23.   

    呵呵……我想ytwxw误会我的意思了。我并不是说自己编写代码去显示数据集,而是根本不打算显示数据集。我显示和处理的是我自己设计的一组对象,它们的数据是从数据集中得来的(不过不一定是一个数据集)。它们由存储管理层负责把数据从数据库中读出来,由界面去处理和显示,然后再由存储管理层负责存储更新。只要把这组对象设计好了,其它的就好办了。
      

  24.   

    伤心的风) 
    呵呵 你的意思是显示通过 SQL塞选出来的数据吗?
      

  25.   

    因此对于这部分逻辑,我们需要重建数据集!
    请问重建数据集什么意思? virtualmfc(scale)
    你是不是在青岛啊?
      

  26.   

    其实在TClientDataSet方面,有几个问题需要解决,一个是是否需要重头编写,我的回答是不需要。但是对于特别的又怎么办?这有办法。另外,多数据集更新时如何处理?尤其是多数据集中有数据表中不存在的字段怎么处理?这都要靠自己的摸索。我在思考这些问题的时候,将这些解决办法写成了非可视组件,用的时候只需要放在Form上,或者中间层上,到时一设置好特殊的地方,提交时自动搞定。不然自己手写,岂不累死?
      

  27.   

    关于架构问题,我觉得还是要具体问题具体分析,没有任何一种架构、方法、理论……可以适用于任何情况。
    我所说的方法是我在项目开发过程中结出来的,因为我现在做的这个项目非常复杂,仅仅领域模型就分了三层,上层的对象要依赖下层的对象来实现。在进行设计时,我感觉很难用Dataset的概念来表达这个领域模型,于是就把它放到存储层的实现上。这样一来,我自然不会使用数据敏感控件来显示了(因为我要显示和处理的是我的领域模型,而不是存储)。目前我还没有使用ClientDataset,因为所有的与存储有关的代码都在同一个服务中。如果系统规模增大,我可能考虑把应用服务分成业务逻辑和存储管理两部分,至于这个层的联系,我的首选就是ClientDataset,这时我会使用在http://expert.csdn.net/Expert/TopicView1.asp?id=1607921这个贴子中提出的结构。
    关于DNA的使用,我个人意见,我觉得DNA其实并不是一种架构,而是提供给你实现你的架构的工具(当然这可能只是名词之争,如果是这样的话,不必花时间争论)。如果你喜欢它的话,尽量在应用服务的设计时多采用一些细粒度、无状态、适应池化和事务处理的COM+组件。有人可能会说,细粒度的COM+组件会严重影响时间效率,事实上,根据我的经验,时间效率会受影响,但并不严重,而它带来的好处却远大于此。如果你觉得DNA不会给你什么好处,那你干脆就不要使用它。重要的还是要根据你的项目具体分析。
      

  28.   

    初学三层架构,有几个小问题望各位大虾指点一下,楼主不会介意吧,呵呵
    1。如何用静态联编的方式调用应用服务器上远程数据模块的接口(用DCOM作为传输协议)
      小弟最初用动态联编的方式,成功:
        DCOMConnection1.AppServer.GetDatabaseName;
            //Getdatabasename是我在应用服务器上定义的一个取得所有数据库名的函数
       想改用静态联编,是不是用以下的代码
        With DCOMConnection1.AppServer as ImyAppServer do GetDatabaseName;书上说类型库必须在客户端注册,要调用bin目录下的tregsvr.exe
      不能成功,对书上说的也不太了解,望指点~~~2.我用上面提到的session控件的Getdatabasename的函数取得可连接的所有数据库名,但不知道如何使用session的gettablename的函数。因为getdatabasename函数是不需要只需要加上要赋值的参数就可以了对不对。但是gettablename数使用的参数有很多
    procedure GetTableNames(const DatabaseName, Pattern: String; Extensions, SystemTables: Boolean; List: TStrings);
    不知道如何设定这个databasename参数,因为在客户端我要选择databasename,它实际是个变量了,望指点~~~~3.再问个简单的
     interface 里的uses和implementation里的uses有什么区别
    我的理解是只有在运行期,要使用到implementation中的函数或过程时才加载uses里的东西,是不是这样~~4.last one 也很简单
     由于刚开始学delphi,我要加上某个函数实现某个功能的时候,都是手动的先到type里声明,再到implementation里完成相关的定义。不知道各位大虾是怎么作的。鞠躬~~~
      

  29.   

    1:企业对象,比如产品对象,人员对象,分别提供相应的接口方法给组织对象调用,主要负责数据的查询,更新等处理。
    怎么查询和修改在一个COm+里,一般查询和修改是分开的!
      

  30.   

    其实对于这个价构只是个想法,也作了一些基本的测试,
    基本能够实现。Oer(jiky) :
    事务不成问题,用com+的事务控制我所说的lookup举个例子:
    我的定单里边有‘客户编号’吧?
    但是我显示的时候想显示成‘客户名称’,而编辑的时候由想对‘客户编号’进行处理。我想这是大家都会遇到的问题,当然有很多方法可以实现,但是我追求的是通用性,最好是在客户端简单的一设置,然大家都可以用,特别是一些对delphi不熟的编码人员。我的思路是:服务器端我不会进行多表查询,也就是所有的数据只是从定单表里查询而来,自然就不会包括客户姓名,所有的只是客户编号,而在客户端显示的时候我要显示成客户姓名,当对客户姓名进行编辑的时候,可以通过查询窗口或者其他手段,但是返回的是客户编号,这样我就可以直接进行update了,服务器端也就不需要太多的逻辑代码,当然业务是要处理的请各位给个建议?
      

  31.   

    microjuz(头)
    你这几个问题我都帮不了哎我队对这些概念性的东西也不是很了解:(sorry了
      

  32.   

    想问问楼主,你的数据库的表(需要查询和修改)是不是一一对应一个Query?
    我的意思是,楼主的数据摸里是不是一个表对应一个Query,一个provider?