在很多情况下,需要直接修改单据的数据包,给基础资料字段赋值;
如单据转换插件中,给基础资料字段赋值:此时没有单据Model.SetValue()方法可以调用,必须直接修改单据数据包。
但如果没有按照正确的方法给基础资料赋值,就可能会为后续代码埋下一个大隐患。
先看看下面的报错情况:
在做发货通知单 下推到销售出库单 保存Save报错 ,报错如下图,我暂存单据手工保存,提交,审核 都没问题这个问题的原因,就是因为插件给物料字段赋值方法错误:给物料字段填写的数据包,并不是物料需要的数据包。
这会导致物料字段的引用属性与引用数据包不匹配。
随后,单据的实体服务规则、保存校验器等,会按照引用属性到数据包取属性值。
如果引用属性与引用数据包不匹配,会取错数!
轻则报错中断,重则蒙混过关,但是数据全错!
原理已经知道了,下面看看典型的错误代码:
//********************************************
// 给基础资料字段赋值,如下方式是错误的:
// 使用了 stockMeta.BusinessInfo.GetDynamicObjectType() 加载基础资料引用数据包
IMetaDataService metaService = ServiceHelper.GetService<IMetaDataService>();
FormMetadata stockMeta = metaService.Load(this.Context, "BD_STOCK") as FormMetadata;
long stockId = Convert.ToInt64(reader["FStockId"]);
IViewService viewService = ServiceHelper.GetService<IViewService>();
DynamicObject[] stockObjs = viewService.LoadFromCache(this.Context,
new object[] { stockId },
stockMeta.BusinessInfo.GetDynamicObjectType());
stockFld.RefIDDynamicProperty.SetValue(newRowObj, stockId);
stockFld.DynamicProperty.SetValue(newRowObj, stockObjs[0]);
//***********************************************
如下是正确代码,请注意与错误代码之间的差别:
//*********************************************
// 给基础字段赋值,如下方式是正确的:
// 必须使用 stockFld.RefFormDynamicObjectType 加载基础资料引用数据包
BaseDataField stockFld = e.TargetBusinessInfo.GetField("FStockId") as BaseDataField;
long stockId = Convert.ToInt64(reader["FStockId"]);
IViewService viewService = ServiceHelper.GetService<IViewService>();
DynamicObject[] stockObjs = viewService.LoadFromCache(this.Context,
new object[] { stockId },
stockFld.RefFormDynamicObjectType);
stockFld.RefIDDynamicProperty.SetValue(newRowObj, stockId);
stockFld.DynamicProperty.SetValue(newRowObj, stockObjs[0]);
//*********************************************
总结:
给基础资料赋值的正确方法,是使用基础资料本身的引用模型(RefFormDynamicObjectType),加载基础资料的数据包,然后填写到单据上。
推荐阅读