二开案例.单据插件.单据打开前重新加载元数据

栏目:云星空知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

二开案例.单据插件.单据打开前重新加载元数据

【应用场景】

元数据异常,且几乎无法找到原因的情况下,可选择在合适的时机,强制性的重新生成元数据。


【案例演示】

应收票据,无故多出来两个字段,导致单据保存异常中断。


【实现步骤】

<1>编写单据插件,代码如下。

using Kingdee.BOS;

using Kingdee.BOS.Cache;

using Kingdee.BOS.Core.Bill;

using Kingdee.BOS.Core.Bill.PlugIn;

using Kingdee.BOS.Core.Bill.PlugIn.Args;

using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;

using Kingdee.BOS.Core.Metadata;

using Kingdee.BOS.Core.Metadata.ControlElement;

using Kingdee.BOS.ServiceHelper;

using Kingdee.BOS.Util;

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Linq;


namespace Jac.XkDemo.BOS.Business.PlugIn

{

    /// <summary>

    /// 【单据插件】单据打开前重新加载元数据

    /// https://vip.kingdee.com/article/239414681620848640

    /// </summary>

    [Description("【单据插件】单据打开前重新加载元数据"), HotUpdate]

    public class ReloadMetadataBeforeOpenBillBillPlugIn : AbstractBillPlugIn

    {

        private BusinessInfo businessInfo;

        private LayoutInfo layoutInfo;


        public override void OnSetBusinessInfo(SetBusinessInfoArgs e)

        {

            base.OnSetBusinessInfo(e);

            if (this.View.OpenParameter != null && this.View.OpenParameter.Status != OperationStatus.ADDNEW)

            {

                // 控制下影响范围,仅在新增单据的时候重新加载元数据

                return;

            }


            var meta = GetNewMetadata(this.View);

            if (meta != null)

            {

                this.businessInfo = meta.BusinessInfo;

                this.layoutInfo = meta.GetLayoutInfo();


                e.BillBusinessInfo = this.businessInfo;

                e.BusinessInfo = this.businessInfo;

            }

        }


        public override void OnSetLayoutInfo(SetLayoutInfoArgs e)

        {

            base.OnSetLayoutInfo(e);

            e.BillLayoutInfo = this.layoutInfo;

            e.LayoutInfo = this.layoutInfo;

        }


        //public override void BeforeCreateModelData(EventArgs e)

        //{

        //    base.BeforeCreateModelData(e);

        //    if (!CheckMetadata(this.View))

        //    {

        //        GetNewMetadata(this.View);

        //        throw new Exception("创建新数据包前检测到元数据异常,请关闭当前界面后重试!");

        //    }

        //}


        public override void AfterCreateModelData(EventArgs e)

        {

            base.AfterCreateModelData(e);

            if (!CheckMetadata(this.View))

            {

                GetNewMetadata(this.View);

                throw new Exception("创建新数据包后检测到元数据异常,请关闭当前界面后重试!");

            }

        }


        public override void LoadData(LoadDataEventArgs e)

        {

            base.LoadData(e);

            if (!CheckMetadata(this.View))

            {

                GetNewMetadata(this.View);

                throw new Exception("加载数据前检测到元数据异常,请关闭当前界面后重试!");

            }

        }


        public override void AfterLoadData(EventArgs e)

        {

            base.AfterLoadData(e);

            if (!CheckMetadata(this.View))

            {

                GetNewMetadata(this.View);

                throw new Exception("加载数据后检测到元数据异常,请关闭当前界面后重试!");

            }

        }


        /// <summary>

        /// 清除元数据缓存,返回新的元数据

        /// </summary>

        /// <param name="view"></param>

        /// <returns></returns>

        private static FormMetadata GetNewMetadata(IBillView view)

        {

            var ctx = view.Context;

            var businessInfo = view.BusinessInfo;

            var formId = businessInfo.GetForm().Id;

            var layoutId = view.OpenParameter.LayoutId;

            // 清除元数据缓存

            ClearMetaCache(ctx, formId);

            // 重新加载元数据

            var meta = FormMetaDataCache.GetCachedFormMetaData(ctx, formId, layoutId);

            return meta;

        }


        /// <summary>

        /// 清除元数据(清内存缓存和数据库缓存)

        /// </summary>

        /// <param name="ctx"></param>

        /// <param name="formId"></param>

        private static void ClearMetaCache(Context ctx, string formId)

        {

            var ids = new List<string>();

            // 获取与当前表单有关系的所有表单Id

            var sql = string.Format(@"SELECT FID FROM T_META_OBJECTTYPE WHERE FMODELTYPEID<600 AND (FID='{0}' OR FINHERITPATH LIKE '%{0}%')", formId);

            var objs = DBServiceHelper.ExecuteDynamicObject(ctx, sql);

            if (objs != null && objs.Count > 0)

            {

                ids.AddRange(objs.Select(obj => obj[0].ToString()));

            }


            // 获取视图,视图的缓存也要清理

            sql = string.Format(@"SELECT b.FID FROM T_META_OBJECTTYPE a 

JOIN T_META_OBJECTTYPEVIEW b ON a.FID=b.FDEPENDENCYOBJECTID

WHERE a.FMODELTYPEID<600 AND (a.FID='{0}' OR a.FINHERITPATH LIKE '%{0}%')", formId);

            objs = DBServiceHelper.ExecuteDynamicObject(ctx, sql);

            if (objs != null && objs.Count > 0)

            {

                ids.AddRange(objs.Select(obj => obj[0].ToString()));

            }


            // 先更新版本号

            sql = string.Format("UPDATE T_META_OBJECTTYPE SET FMAINVERSION='{0}' WHERE FID IN ({1})", DateTime.Now.Ticks.ToString(), string.Join(",", ids.Select(o => "'" + o + "'")));

            DBServiceHelper.Execute(ctx, sql);

            // 再删除数据库缓存

            sql = string.Format("DELETE FROM T_META_OBJECTTYPECACHE WHERE FID IN ({0})", string.Join(",", ids.Select(o => "'" + o + "'")));

            DBServiceHelper.Execute(ctx, sql);

            // 再删除内存缓存

            var kcmgr = KCacheManagerFactory.Instance.GetMetadataCacheManager(ctx);

            if (kcmgr != null)

            {

                foreach (var id in ids)

                {

                    kcmgr.Remove(id);

                }

            }

        }


        /// <summary>

        /// 检查元数据是否正常

        /// </summary>

        /// <param name="view"></param>

        /// <returns></returns>

        private static bool CheckMetadata(IBillView view)

        {

            var dy = view.BillBusinessInfo.GetDynamicObjectType();

            if (dy.Properties.Contains("Number") && dy.Properties.Contains("FCheckBox"))

            {

                return false;

            }


            dy = view.BusinessInfo.GetDynamicObjectType();

            if (dy.Properties.Contains("Number") && dy.Properties.Contains("FCheckBox"))

            {

                return false;

            }


            dy = view.Model.BillBusinessInfo.GetDynamicObjectType();

            if (dy.Properties.Contains("Number") && dy.Properties.Contains("FCheckBox"))

            {

                return false;

            }


            dy = view.Model.BusinessInfo.GetDynamicObjectType();

            if (dy.Properties.Contains("Number") && dy.Properties.Contains("FCheckBox"))

            {

                return false;

            }


            return true;

        }

    }

}


<2>拷贝插件组件到应用站点的WebSite\Bin目录下,重启IIS。


<3>BOSIDE扩展应收票据,注册表单插件,保存元数据,开发完毕。

---------------------------------------------------------------------------------------------------------













【金蝶云星空BOS二次开发案例演示】https://vip.kingdee.com/article/94751030918525696

【C#】【单据插件】单据打开前重新加载元数据.rar

【Python】【单据插件】单据打开前重新加载元数据.rar

二开案例.单据插件.单据打开前重新加载元数据

【应用场景】元数据异常,且几乎无法找到原因的情况下,可选择在合适的时机,强制性的重新生成元数据。【案例演示】应收票据,无故多出来两...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息