c# 遞迴應用 完成js檔案自動參照

2023-03-10 12:01:36

背景:

  兩張表,分別是 :sys_tbl,和 sys_field,其中:sys_tbl 是系統所有表的資訊,包含兩個欄位 :code(表名),name(表描述資訊);sys_fld 是記錄第張表中的欄位 的名稱(field)和描述資訊(table) , 

截圖如下:

sys_tbl

  

 

 

 其中,欄位 名稱包含對其它名稱(物件) 的參照,寫法為:表名(去除下劃線)_參照欄位 ,如:einventory_cinvcode,就是對錶 e_inventory 中欄位 cinvcode的參照。

 每張表都在系統 中對應有不同功能的js檔案(模組)如: 編輯表單(dialog型別),跨域選擇表單(field)型別等

 需求:

在一個綜合的頁面中,會對其它物件進行參照(依賴),而這種參照最終體現在對js檔案的包含。同時被參照的js 檔案(一級參照)還有自已關聯物件(二級參照).....如此下去,直到N 級參照。

所以現在需要逐層找到物件的參照,直到最後不依賴任何物件為止,並把這些js檔案生成參照包含路徑(不重複)

 

分析:

1、返回結果型別:

得到這些js參照,不能重複,但是物件之間參照是可以存在交叉的,在整個參照鏈條上,同一個物件會被 多個物件參照,所以簡單的字串陣列是避免不了重複的。但是在C#中的HashSet可以做到不重複,同時這個去重工作是自動完成的,所以存結果如果是簡單的value型別,用 HashSet就可以,但是因為欄位中表的資訊已經被格式化過,所以還要把格式化之前的表名稱取出與欄位對應,所以需要一個key-value型別的資料 ,那就是 Dictionary<string, string> 了。

2、演演算法選擇

因為查詢參照,是層層進行的,而且下一層參照的要用到上一層的參照結果,所以這裡選擇遞迴演演算法

程式碼實現:

宣告一個全域性變數,記錄所有的表與欄位的對應的資料,因為需要確保資料key 唯一性所以選擇Dicctionary型別

        /// <summary>
        /// define the gloable parameter to save the rel obj data
        /// </summary>
        public static Dictionary<string, string> deepRef = new Dictionary<string, string>();

入口函數,完成準備工作,(資料庫連線,引數準備)

         /// <summary>
        /// 通過表的欄位 獲取相關的參照欄位依賴的物件 直到沒有依賴為止
        /// </summary>
        /// <param name="headField">表欄位列表</param>
        /// <returns></returns>
        public static Dictionary<string,string>  getRelRef(List<IniItemsTableItem> headField)
        {
            HashSet<string> refset = new HashSet<string>();
           // HashSet<string> refset_result = new HashSet<string>();
            foreach (var item in headField)
            {
                if (!item.controlType.StartsWith("hz_"))// is not the field of  reference
                {
                    continue;
                }
                string[] fieldarr = item.dataIndex.Split('_');//the constructor is :[tabble]_[field]

                refset.Add(fieldarr[0]);//the first prefix

            }
            dataOperate dao = new dataOperate();
            dao.DBServer = "info";
            SqlConnection conn = dao.createCon();
            try
            {
                if (refset.Count > 0)
                {
                    
                    if (conn.State != ConnectionState.Open)
                        conn.Open();//open connection
                    deepRef = new Dictionary<string, string>();//clear the relation obj data
                    getRef(conn, refset);
                 

                }
                return deepRef;
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                if (conn.State == ConnectionState.Open)
                    conn.Close();
            }

        }

遞迴函數,最終完成在資料庫中獲取欄位依賴的物件的獲取

        /// <summary>
        /// get the relation obj 
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="ref_field"></param>
        /// <returns></returns>
        public static HashSet<string> getRef(SqlConnection conn, HashSet<string> ref_field)
        {
            HashSet<string> refset = new HashSet<string>();

            string refstr = string.Join("','", ref_field);
            if (refstr != "")
            {
                refstr = "'" + refstr + "'";

                string sql = "SELECT dbo.GetSplitOfIndex(b.[field],'_',1) as refcode,a.[code]  FROM   (  select   replace(code,'_','') as uncode,* from     [SevenWOLDev].[dbo].[sys_tbl_view] )   as a inner join [SevenWOLDev].[dbo].[sys_fld_view]  as b    on a.uncode=dbo.GetSplitOfIndex(b.[field],'_',1)    where replace([table],'_','') in (" + refstr + ") and uitype='ref'";
                //get dataset relation obj
                DataSet ds = dataOperate.getDataset(conn, sql);
                if (ds != null && ds.Tables.Count > 0)
                {
                    DataTable dt = ds.Tables[0];
                    if (dt.Rows.Count > 0)
                    {
                        //rel ref exists
                        for (int k = 0; k < dt.Rows.Count; k++)
                        {
                            string vt = dt.Rows[k].ItemArray[0].ToString();
                             string vv = dt.Rows[k].ItemArray[1].ToString();
                            refset.Add(vt);//save current ref
                            if(!deepRef.ContainsKey(vt))
                                deepRef.Add(vt, vv);// save all ref

                             
                        }
                        if (refset.Count > 0)// get the ref successfully
                        {
                            //recursion get
                            getRef(conn, refset);
                        }

                    }

                }

            }
            else
            { 
                //no ref
            }
            return refset;
        }

對函數進行呼叫,並組織出js檔案參照路徑

 Dictionary<string,string> deepRef = ExtjsFun.getRelRef(HeadfieldSetup);
            if (deepRef != null)
            {
                foreach (var s in deepRef)
                {
                    string tem_module = "";
                    tem_module = s.Value;
                    string[] moduleArr = tem_module.Split('_');
                    if (tem_module.IndexOf("_") >= 0)
                        tem_module = moduleArr[1];//module name for instance: p_machine ,the module is 「machine」 unless not included the underscore
                    string fieldkind = "dialog";
                    jslist.Add(MyComm.getFirstUp(tem_module) + "/" + ExtjsFun.GetJsModuleName(tem_module, s.Value, fieldkind) + ".js");
                    fieldkind = "field";
                    jslist.Add(MyComm.getFirstUp(tem_module) + "/" + ExtjsFun.GetJsModuleName(tem_module, s.Value, fieldkind) + ".js");
                }
            }

 

最終結果 如下:

      <script src="../../dept/demoApp/scripts/Sprice/SpriceE_spriceGridfield.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Org/OrgE_orgDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Supplier/SupplierOa_supplierDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Supplier/SupplierOa_supplierField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Unit/UnitE_unitDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Unit/UnitE_unitField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Wh/WhWh_whDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Wh/WhWh_whField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Mold/MoldP_moldDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Mold/MoldP_moldField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Suppliercategory/SuppliercategoryOa_suppliercategoryDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Suppliercategory/SuppliercategoryOa_suppliercategoryField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Bank/BankOa_bankDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Bank/BankOa_bankField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Machine/MachineP_machineDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Machine/MachineP_machineField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Inventory/InventoryE_inventoryDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Basedocment/BasedocmentOa_basedocmentDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Basedocment/BasedocmentOa_basedocmentField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Basedoctype/BasedoctypeOa_basedoctypeDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Basedoctype/BasedoctypeOa_basedoctypeField.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Tax/TaxE_taxDialog.js" type="text/javascript"></script>
      <script src="../../dept/demoApp/scripts/Tax/TaxE_taxField.js" type="text/javascript"></script>

 

 

完事程式碼如下:

/// <summary>
        /// define the gloable parameter to save the rel obj data
        /// </summary>
        public static Dictionary<string, string> deepRef = new Dictionary<string, string>();
        /// <summary>
        /// 通過表的欄位 獲取相關的參照欄位依賴的物件 直到沒有依賴為止
        /// </summary>
        /// <param name="headField">表欄位列表</param>
        /// <returns></returns>
        public static Dictionary<string,string>  getRelRef(List<IniItemsTableItem> headField)
        {
            HashSet<string> refset = new HashSet<string>();
           // HashSet<string> refset_result = new HashSet<string>();
            foreach (var item in headField)
            {
                if (!item.controlType.StartsWith("hz_"))// is not the field of  reference
                {
                    continue;
                }
                string[] fieldarr = item.dataIndex.Split('_');//the constructor is :[tabble]_[field]

                refset.Add(fieldarr[0]);//the first prefix

            }
            dataOperate dao = new dataOperate();
            dao.DBServer = "info";
            SqlConnection conn = dao.createCon();
            try
            {
                if (refset.Count > 0)
                {
                    
                    if (conn.State != ConnectionState.Open)
                        conn.Open();//open connection
                    deepRef = new Dictionary<string, string>();//clear the relation obj data
                    getRef(conn, refset);
                 

                }
                return deepRef;
            }
            catch (Exception)
            {

                throw;
            }
            finally
            {
                if (conn.State == ConnectionState.Open)
                    conn.Close();
            }


            

        }
       
        /// <summary>
        /// get the relation obj 
        /// </summary>
        /// <param name="conn"></param>
        /// <param name="ref_field"></param>
        /// <returns></returns>
        public static HashSet<string> getRef(SqlConnection conn, HashSet<string> ref_field)
        {
            HashSet<string> refset = new HashSet<string>();

            string refstr = string.Join("','", ref_field);
            if (refstr != "")
            {
                refstr = "'" + refstr + "'";

                string sql = "SELECT dbo.GetSplitOfIndex(b.[field],'_',1) as refcode,a.[code]  FROM   (  select   replace(code,'_','') as uncode,* from     [SevenWOLDev].[dbo].[sys_tbl_view] )   as a inner join [SevenWOLDev].[dbo].[sys_fld_view]  as b    on a.uncode=dbo.GetSplitOfIndex(b.[field],'_',1)    where replace([table],'_','') in (" + refstr + ") and uitype='ref'";
                //get dataset relation obj
                DataSet ds = dataOperate.getDataset(conn, sql);
                if (ds != null && ds.Tables.Count > 0)
                {
                    DataTable dt = ds.Tables[0];
                    if (dt.Rows.Count > 0)
                    {
                        //rel ref exists
                        for (int k = 0; k < dt.Rows.Count; k++)
                        {
                            string vt = dt.Rows[k].ItemArray[0].ToString();
                             string vv = dt.Rows[k].ItemArray[1].ToString();
                            refset.Add(vt);//save current ref
                            if(!deepRef.ContainsKey(vt))
                                deepRef.Add(vt, vv);// save all ref

                             
                        }
                        if (refset.Count > 0)// get the ref successfully
                        {
                            //recursion get
                            getRef(conn, refset);
                        }

                    }

                }




            }
            else
            { 
                //no ref
            }
            return refset;
        }