关于BOS中的标识、字段名、实体属性名的开发应用简介原创
金蝶云社区-CQ周玉立
CQ周玉立
67人赞赏了该文章 8996次浏览 未经作者许可,禁止转载编辑于2022年07月13日 16:02:04

BOS中有三个迷惑的"标识",最近看到社区有小伙伴在咨询"关于BOS中的标识、字段名、实体属性名的开发应用"。

官方知识有一个简单的介绍https://vip.kingdee.com/questions/7453/answers/10947


结合个人理解,开发相关具体用法简单介绍一下。



1.标识:在整个单据中要唯一,可以理解成字段控件的标识。

用法一:需要通过插件对字段控件做界面属性的控制时使用。

例如,代码控制字段的锁定性,可见性;修改字段的颜色;修改字段标题;插件中捕获触发事件的字段也是匹配的标识....等等。

用法二:通过"界面的方式"获取字段的值,给字段赋值、刷新字段、或者代码触发字段的值更新,实体服务规则。

例如,this.View.Model.SetValue、this.View.Model.GetValue、this.View.InvokeFieldUpdateService、this.View.RuleContainer.RaiseDataChanged....等等。

用法三:WebAPI接口调用时使用。


2.字段名:这个是最好理解的,指的是字段在他所在数据库表中的字段名称,所以在数据库表中唯一。

用法一:通过SQL查询数据库表时,通过字段名获取字段,或者作为关联字段、条件过滤字段。我们需要搞清楚的是,单据上的字段名在数据库表中存的是什么?

例如,基础资料/辅助资料存的是主键内码、普通字段(数值、文本、日期等)存的是原值、枚举字段存的是枚举值...等等。

用法二:我们经常会用视图绑定二开单据,来实现不同单据从数据库中取同一套物理数据,既能帮我们免去很多数据同步自动生成的烦恼,又能节约数据库空间。这里我们就需要将字段名设置成视图中的字段名,从而实现“单据字段从视图中读取值”的效果。

例如,标准产品中,销售订单这个单据是以单据的形式存在于销售管理模块,那么出纳模块中需要调用销售订单,比如手动做预收款时,需要勾稽销售订单号,那么出纳模块通过视图读取销售订单的部分关键数据构建成一个视图基础资料(V_CN_SALORDER),基础资料的表名绑定构建好的视图,添加的所有字段名都绑定视图里面的字段,只要满足用法一中所提及的“不同字段类型,在数据表中存储的是不同意义的数据”这样一个存储规则,那么销售订单单据和销售订单基础资料就是自动同步的,这种用法很有技巧性,而且有很大的用处,应用场景广泛!


3.实体属性名:表示单据实体数据包中的标识,在实体中唯一。扩展知识:实体和表是一对多的关系。

用法介绍:主要是在插件中操作单据数据包时使用,这里可以类比一下MVC模式(M层:实体属性名,V层:标识,C层:字段名),在不同层操作时,就需要用到不同的标识。

主要是对DynamicObject类型的数据包进行读写,会用到这个实体属性名,这个用法非常重要,是插件开发必不可少的知识重点。初学者可以类比JSON对象来进行理解,可以通过实体属性标识对数据包里面的字段进行读写。

        DynamicObject可以相当于一个JSON对象,数据包里面的字段有多种类型,读写的时候,需要"一层一层剥开"去进行操作。一个单据的数据包就是一个DynamicObject,单据的数据包里面有很多类型的数据,其实字段是绑定到实体里面的,从M层这个角度来讲,除了纯布局显示控件,一个单据是由多个实体组成的(BOS中有单据头、子单据头、单据体、子单据体这4种实体),不知道大家有没有注意到,BOS中的字段都有一个【实体】的设置,当我们添加字段的时候,如果拖到单据头,那默认就是单据头,拖到单据体默认就是单据体,实际上这个设置也是可以修改的,拖到单据头的字段可以修改到其他子单据头。单据体则只能绑定字段所在的单据体。

与JSON不同的是,每一个DynamicObject都有自己特定的类型,对应了自己的一个结构,数据包里面的字段属性就是他包含的所有实体属性名,不能像JSON那样随意添加、删除字段属性。 

获取类型的代码:

billObj = this.View.Model.DataObject;

objType=billObj .DynamicObjectType;

如果是单据体行的话:

entity=billObj["单据体ORM实体标识"];

rowType=entity.DynamicCollectionItemPropertyType;

如果需要实例化一个DynamicObject必须要传入类型,以此来定义这个数据包的结构:

newObj=new DynamicObject(objType);


        当我们通过实体属性名在操作数据包中字段的时,首先需要获取到字段所在的实体,再往下一层去获取字段。

单据头字段在最外层,可以直接通过"单据的数据包["实体属性名"]"获取。

   这里以表单插件为例(本文代码示例为Python写法,C#写法类似),

   其他插件类型通常也有方法获取单据的数据包(例如最常见的load方法)

//获取单据的数据包:

        billObj = this.View.Model.DataObject;

//获取单据头字段:

    billNo=billObj["字段实体属性标识"];//单据编号、或者其他普通字段

//获取客户基础资料,注意:当字段类型是基础资料或者辅助资料时,

//直接获取到的是资料的数据包(相当于基础资料单据的数据包),也是一个DynamicObject。

//如果进一步获取基础资料的属性,再往下一层获取即可,需要注意的是,需要获取的字段要在【引用属性】里面添加!

    custObj=billObj["字段实体属性标识"];//客户资料

   custNum=custObj["Number"];//客户编码,Number是客户编码的绑定实体属性,系统默认是没加"F"的

//获取单据体 :单据体是一个集合DynamicObjectCollection类型,

//其中的每一行又是一个DynamicObject,逐行解析字段即可。

    entity=billObj["单据体ORM实体标识"];

//循环获取单据体里面的每一行:

    for r in entity:

          fld1=r["单据体字段实体属性标识"];

同样的,和JSON类似,也可以修改数据包里面的数据,需要注意的是,修改的时候原字段是什么类型就赋值什么类型,例如,原字段是一个基础资料,那么赋值也应该赋值同类型的DynamicObject数据包,同时还要赋值内码才行。

       billObj["字段实体属性标识"]=CustObj;

//资料类型的字段都会自动有一个内码字段,实体属性名为:原资料实体属性名_Id

      billObj["字段实体属性标识_Id"]="XXX";

//修改单据体字段,同样需要循环:

     for r in entity:

          r["单据体字段实体属性标识"]="XXX";

修改完之后调用BusinessDataServiceHelper.Save方法就可以将更新后的数据包保存到数据库,通过此方法保存数据会经过应用层的校验规则以及数据类型的合法性等等,比直接更新数据库更加可靠安全!

     

好了,就分享到这里了,大概涉及到的就是这些内容,但是要熟练应用还是要多理解、多练习、多验证,加油!



赞 67