思考探索,如何才能高效訪問我的這個DataTable?


需求

一切都是空的,除了Money,只有需求才是最真的,你懂的。

最近接到個略顯棘手的需求,思索再三,想出兩種方法,可覺得都不太好,這里與大家討論一下。

需求如下:

用戶需要在現有的某個grid中添加新的一列: Des。現有grid的所有數據DataTable:OraDt都來自一個oracle數據庫,而新加的Des值卻來自別的四個sqlserver數據庫中的某一個。四個SqlServer數據庫CHNDB,JPNDB,USDB,CANDB的結構相同,只是數據不同。

根據兩個變量:geo和desID可以從前面sql DB中中得到Des的值。geo確定從哪個sql數據庫中獲取,desID用來得到des的值。 geo和desID就在OraDt中存着,如何才能高效的獲取des的值?

geo與sqlserver db對應關系如下:

Geo值 Sqlserver DB
CHN  CHNDB
 JPN  JPNDB
 US  USDB
 CAN  CANDB

解決思路

  1. 從Oracle數據庫的某表中查詢數據,得到DataTab:OraDt;
  2. OraDt中添加新列: DataColumn("Des", typeof(string));
  3. 遍歷OraDt的每一個datarow,取得不同的geo和desID的值;
  4. 根據geo和desID的值確定Sqlserver DB並獲得des的值;
  5. 更新OraDt中新列row["Des]的值

解決方案偽代碼

  • 這種方法思路比較簡單,老老實實遍歷OraDt的每一個datarow,取得不同的geo和desID的值,然后從對應的sqlser數據庫中獲取des的值:
  //得到oracle datatable,添加row[des],遍歷datatable,獲取des的值,更新des
        protected void ProcessDataTable()
        {
           //添加新列
            _ds.Tables[0].Columns.Add(new DataColumn("Des", typeof(string)));
            string desID = string.Empty;
            string geo = string.Empty;

            //遍歷OraDt
            foreach (DataRow row in _ds.Tables[0].Rows)
            {
                if (row["desID"] != DBNull.Value)
                    desID = row["desID"].ToString();

                if (!string.IsNullOrEmpty(desID) )
                {
                   //得到geo
                    switch (row["countryId"].ToString())
                        {
                            case Country.US:
                                geo = "US";
                                break;
                            case Country.China:
                                geo = "CHA";
                                break;
                            case Country.Canada:
                                geo = " CAN";
                                break;
                            case Country.Jpan:
                                geo = "JPN";
                                break;
                        }
                    //得到添加des
                    row["Des"]= GetExemptionDes(geo, desID);
                    }
                else row["Des"] = string.Empty;
                }
            }

 GetExemptionDes的代碼:

        private string GetExemptionDes(string geo, string desid)
        {
            string description = string.Empty;
            string query = "select des from taxDes where desid="+desid;
            //確定哪個DB獲取數據
            Database DbGEO = DbGEOFactory.CreateDatabase(geo);
            System.Data.Common.DbCommand sqlCmd = DbGEO.GetSqlStringCommand(query);
            //獲得des值
            using (IDataReader dr = DbGEO.ExecuteReader(sqlCmd))
            {
                while (dr.Read())
                {
                    if (dr["des"] != null)
                        description = dr["des"].ToString();
                }
                dr.Close();
            }
            return description;
        } 

性能探究:

這種想法思路簡單,問題也顯而易見,雖然通常情況下OraDt只有十幾個row,可極個別時候OraDt的row能達到上千個,這時候,上面的方法要連續訪問 Sqlserver DB上千次,顯然嚴重影響了性能。有某有其他的好方法呢?

第二方案,或者其他更好的解決方法?

由於geo最多只有四個,所以我們可以把相同geo下的desID拼接起來,最后一塊訪問sqlserver db,這樣最多只需要訪問四次,思路:

      前三步與上面方法一樣,

     4.根據geo把desid拼接於一個string變量中

     5.最后一起訪問sqlserver db

     6.獲得des值,

     7.OraDt更新des

第二方法缺憾:

大量datatable的操作實際上也影響了代碼的效率,而且OraDt的數據量通常只有幾十行,用這種方法處理普通的OraDt時候顯然太過繁瑣。

可是現在看來似乎只有這兩種方法來解決這個問題了,難道真的就由這么個性能問題存在於我們的代碼中么?哪位如果有什么新的解決思路,可以一起分享一下,一起進步。

第一種方法和第二種到底用哪一種好呢?

現將第二方案的詳細代碼列示如下,由於寫的匆忙,還未來的及調試,有什么問題或者哪里可以改進,希望大家多多指正。

可以看到這種方法繁瑣操縱OraDt,尤其是在方法UpdateOraDT中,由於某種原因不能使用Linq 來連接datatable,三個foreach 嵌套起來簡直不堪入目。處理普通的OraDt時候明顯會帶來性能問題:

protected  void ProcessDataTable()
        {
            _ds.Tables[0].Columns.Add(new DataColumn("ExemptionDes", typeof(string)));

            string desID = string.Empty;
            string geo = string.Empty;

            //建造一個鋸齒數組,[0]:geo,[1]: 該geo是否需要被訪問,默認0表示不需要,[3]用來拼接desID
            string[][] geoExistArray = new string[4][] { 
                              new string[] { "NA", "0","" },
                              new string[] { "LA", "0","" },
                              new string[] { "EMEA", "0","" },
                              new string[] { "AP", "0","" },
            };
            //遍歷datatable
            foreach (DataRow row in _ds.Tables[0].Rows)
            {
                if (row["desID"] != DBNull.Value)
                {
                    xmtn_ID = row["desID"].ToString();
                }

                //如果desID為空,直接將des設置為0
                //不為空,則遍歷datatable,取des值
                if (!string.IsNullOrEmpty(desID))
                {
                    switch (row["countryId"].ToString()) {
                        case Country.US:
                            geo = "US";
                            geoExistArray[0][0] = "1";
                            geoExistArray[0][2] = geoExistArray[0][2] + desID+ ",";
                            break;
                        case Country.China:
                            geo = "CHN";
                            geoExistArray[1][0] = "1";
                            geoExistArray[1][2] = geoExistArray[1][2] + desID+ ",";
                            break;
                        case Country.Canada:
                            geo = "CAN";
                            geoExistArray[2][0] = "1";
                            geoExistArray[2][2] = geoExistArray[2][2] + desID+ ",";
                            break;
                        case Country.Jpan:
                            geo = "JPN";
                            geoExistArray[3][0] = "1";
                            geoExistArray[3][2] = geoExistArray[3][2] + desID+ ",";
                            break;
                    }
                }
                else row["Des"] = string.Empty;
            }

            //移除每個拼出的desID字符串中的最后一個逗號
            foreach (var array in geoExistArray)
            {
                if (array[3].Length > 0)
                    array[3].Remove(array[3].Length - 1, 1);
            }
            //獲取des值並更新OraDT
            UpdateOraDT(_ds.Tables[0], geoExistArray);
        }

UpdateOraDT代碼:

        private DataTable UpdateOraDT(DataTable dt, string[][] geoExistArray)
        {
            DataTable ExemDesDT;
            foreach (var GeoArrary in geoExistArray)
            {
                //得出一個需要被訪問的sql db下的所有des,存於ExemDesDT 
                if (GeoArrary[1] == "1")
                {
                    ExemDesDT = GetExemptionDesSQL(GeoArrary[0], GeoArrary[2]);
                    if (ExemDesDT != null)
                        //遍歷ExemDesDT,如果ExemDesDT中的id_exemption等於OraDt中的desID ,則獲取des
                        foreach (DataRow pyrow in ExemDesDT.Rows)
                        {
                            foreach (DataRow phxrow in dt.Rows)
                            {
                                if (pyrow["id_exemption"] == phxrow["desID"])
                                    phxrow["ExemptionDes"] = pyrow["description"].ToString());
                            }
                        }
                }
            }
            return dt;
        }

  

GetExemptionDesSQL方法:
       private DataTable GetExemptionDesSQL(string geo, string desidList)
        {
            DataTable ExemDesDT = new DataTable();
            string query = " select des from taxDes where desid in (" + desidList+")";
            Database DbGEO = DbGEOFactory.CreateDatabase(geo);
            System.Data.Common.DbCommand sqlCmd = DbPyramid.GetSqlStringCommand(query);
            ExemDesDT = DbGEO.ExecuteDataSet(sqlCmd).Tables[0];
            return ExemDesDT;
        }

 

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM