zoukankan      html  css  js  c++  java
  • 让kbmMWClientQuery更新视图

    先说下问题,有一个物理表t1,基于t1,建立一个视图v1,然后用ClientQuery查询视图:
    ClientQuery.Query.Text:='Select f1,f2 from v1'
    查询到结果后,增删改记录,然后:
    ClientQuery.Resolve提交修改结果,问题出现:

    当ClientQuery.TableName='t1'时,可以提交,等于'v1'时,无法提交,生成一个无字段的sql
    Insert into v1 ( ) values ( )

    那如何让ClientQuery.TableName='v1'时也能正常提交呢?


    解决方法:在运行期修改Field.Origin值
    ClientQuery.FieldByName('f1').Origin:='v1.f1';
    ClientQuery.FieldByName('f2').Origin:='v1.f2';
    或者:
    ClientQuery.FieldByName('f1').Origin:='.f1';
    ClientQuery.FieldByName('f2').Origin:='.f2';
    或者:
    ClientQuery.FieldByName('f1').Origin:='';
    ClientQuery.FieldByName('f2').Origin:='';

    视图能正常更新了!注意,必须在运行期用代码来修改Origin,设计期不行的。

    进一步分析原因,在ClientQuery.Open后,ClientQuery.FieldByName('f1').Origin等于't1.f1',也就是查询视图,这里返回实际物理表名,在服务端解析时,如果ClientQuery.TableName=v1,与字段的Origin中的物理表名t1不一致,造成无法生成正确的sql语句。

    具体的逻辑在TkbmMWCustomTableFieldResolver.BuildFieldFilter方法中实现,感兴趣可以去看看。

    通过查看这个方法,得知,当设置Origin为空时,还受kbmMWUNIDACResolver.SkipFieldsWithoutOrigin属性控制,当为True时,则不处理这个字段,默认值为False,即处理Origin为空的字段。

    写到这里,也许你已经想到,不仅对于View的更新操作,我们完全可以通过设置ClientQuery.TableName及Field.Origin属性,实现ClientQuery.Resolve的更新行为。这必须为kbmMW赞一个!

    最后,感谢Q友不会呼吸274001335,帮我跟踪了好几天,最终搞清这块的逻辑,同时感谢作者kim在news group 上的支持与回复!

    下面按不会呼吸的想法,利用Class Helper来修改ClientQuery.Open的行为:

    //声明kbmMWClientQuery的Helper类:
      TkbmMWClientQueryHelper=class helper for TkbmMWClientQuery
        procedure Open;
      end;
    
    //重新实现kbmMWClientQuery.Open方法
    { TkbmMWClientQueryHelper }
    
    procedure TkbmMWClientQueryHelper.Open;
    var
      i:Integer;
    begin
      inherited Open;
      for I := 0 to Self.FieldCount-1 do
      begin
        if Self.Fields[i].Origin.Substring(0,1)<>'.' then //如果是虚字段则设置为一个不存在的表名,保证不生成到sql里去更新
    //      Self.Fields[i].Origin:=Self.TableName+'.'+Self.Fields[i].FieldName
          Self.Fields[i].Origin:='.'+Self.Fields[i].FieldName
    //      Self.Fields[i].Origin:=''
        else
          //如果是sql中的虚字段则设置为一个不存在的表名,保证不生成到sql里去更新,避免出错.
          Self.Fields[i].Origin:='xxxxxxxxxx.'+Self.Fields[i].FieldName;
    
      end;
    
    end;

    对于Helper Class,执行ClientQuery.Open的单元,必须引用这个Helper类所在的单元,否则不会执行上面的代码!

    上面的方法,只是解决当查询一个视图时,自动不提交虚拟字段,那对于下面朋友遇到的问题,又如何处理呢?

    朋友HY遇到这样的问题,查询视图,还要修改视图并提交修改结果,因为是视图,有些字段不需要提交到后台。
    查了下新闻组,作者提到几种方法可以控制提交哪些字段到后台:
    方法一:
    通过设置TField.Origin属性,需要提交的填上内容,不需要为空,然后设置服务端的Resolver.SkipFieldWithoutOrigin=True;

    方法二:
    通过设置TField.ProviderFlags属性,不需要提交的将pfInUpdate去掉。通过这个属性还可以进一步控制字段是否出现在Where子句中。

    procedure TPersonManagerFrame.qOneTableAfterOpen(DataSet: TDataSet);
    begin
      inherited;
      //不更新这两个字段.
      DataSet.FieldByName('FPositionName').ProviderFlags := DataSet.FieldByName('FPositionName').ProviderFlags- [pfInUpdate,pfInWhere];
      DataSet.FieldByName('FPositionID').ProviderFlags := DataSet.FieldByName('FPositionID').ProviderFlags- [pfInUpdate,pfInWhere];
    end;


    方法三:
    处理Resolver的事件:ExcludeFromUpdateInsert和ExcludeFromWhere,简单返回字段的ProviderFlags,类似方法二。

    最后,想说的是:选择kbmMW做你的多层框架,没错的! 
  • 相关阅读:
    【好书摘要】性能优化中CPU、内存、磁盘IO、网络性能的依赖
    【转】性能调优从哪里入手
    【转】从来没有冲突的团队是最糟糕的团队
    【转】华为Java编程军规,每季度代码验收标准
    【转】性能测试随笔,看看罢了,只做笑谈尔。
    MVC的JsonResult用法
    artDialog
    js apply/call/caller/callee/bind使用方法与区别分析
    jquery的each()详细介绍
    ASP.NET 4.5.256 has not been registered on the Web server
  • 原文地址:https://www.cnblogs.com/kinglandsoft/p/13692824.html
Copyright © 2011-2022 走看看