2017-06-22 29 views
0

我使用ADO.NET over Entity Framework來獲得高性能,因爲我的應用程序的數據複雜度有點高。因此,有混淆以下兩種方法:將數據錶轉換爲列表<T>(模型類列表)通用方法性能

方法1 - 通用方法對於所有

我使用下面的泛型方法對數據錶轉換成相應的模型對象。在這裏它使用反射並匹配模型的所有屬性和地圖的數據表頭,並構建適當的列表。

#region ConvertToList 
     /// <summary> 
     /// DataTableToList --- This function is used to Convert DataTable to List 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     public static List<T> DataTableToList<T>(DataTable dtDataCollection) where T : new() 
     { 
      var objList = new List<T>(); 

      //Define what attributes to be read from the class 
      const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance; 

      //Read Attribute Names and Types 
      var objFieldNames = typeof(T).GetProperties(flags).Cast<PropertyInfo>(). 
       Select(item => new 
       { 
        Name = item.Name.ToLower(), 
        Type = Nullable.GetUnderlyingType(item.PropertyType) ?? item.PropertyType 
       }).ToList(); 

      //Read Datatable column names and types 
      var dtlFieldNames = dtDataCollection.Columns.Cast<DataColumn>(). 
       Select(item => new 
       { 
        Name = item.ColumnName.ToLower(), 
        Type = item.DataType 
       }).ToList(); 

      foreach (DataRow dataRow in dtDataCollection.AsEnumerable().ToList()) 
      { 
       var classObj = new T(); 

       foreach (var dtField in dtlFieldNames) 
       { 
        PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 

        var field = objFieldNames.Find(x => x.Name == dtField.Name); 

        if (field != null) 
        { 

         if (propertyInfos.PropertyType == typeof(DateTime)) 
         { 
          propertyInfos.SetValue 
          (classObj, convertToDateTime(dataRow[dtField.Name]), null); 
         } 
         else if (propertyInfos.PropertyType == typeof(int)) 
         { 
          propertyInfos.SetValue 
          (classObj, ConvertToInt(dataRow[dtField.Name]), null); 
         } 
         else if (propertyInfos.PropertyType == typeof(long)) 
         { 
          propertyInfos.SetValue 
          (classObj, ConvertToLong(dataRow[dtField.Name]), null); 
         } 
         else if (propertyInfos.PropertyType == typeof(decimal)) 
         { 
          propertyInfos.SetValue 
          (classObj, ConvertToDecimal(dataRow[dtField.Name]), null); 
         } 
         else if (propertyInfos.PropertyType == typeof(Boolean)) 
         { 
          propertyInfos.SetValue 
          (classObj, ConvertToBool(dataRow[dtField.Name]), null); 
         } 
         else if (propertyInfos.PropertyType == typeof(String)) 
         { 
          if (dataRow[dtField.Name].GetType() == typeof(DateTime)) 
          { 
           propertyInfos.SetValue 
           (classObj, ConvertToDateString(dataRow[dtField.Name]), null); 
          } 
          else 
          { 
           propertyInfos.SetValue 
           (classObj, ConvertToString(dataRow[dtField.Name]), null); 
          } 
         } 
        } 
       } 
       objList.Add(classObj); 
      } 
      return objList; 
     } 


     /// <summary> 
     /// ConvertToDateString --- This function is used to convert object to DateString 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     private static string ConvertToDateString(object dtValue) 
     { 
      if (dtValue == null && dtValue == DBNull.Value) 
       return string.Empty; 

      //return SpecialDateTime.ConvertDate(Convert.ToDateTime(date)); 
      return Convert.ToString(dtValue); 
     } 


     /// <summary> 
     /// ConvertToString --- This function is used to convert object to string    
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 


     private static string ConvertToString(object strValue) 
     { 
      // return Convert.ToString(HelperFunctions.ReturnEmptyIfNull(value)); 
      string returnValue = string.Empty; 
      if (strValue != null && strValue != DBNull.Value) 
       returnValue = Convert.ToString(strValue); 
      return returnValue; 
     } 


     /// <summary> 
     /// ConvertToInt --- This function is used to convert object to Int    
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     private static int ConvertToInt(object iValue) 
     { 
      //return Convert.ToInt32(HelperFunctions.ReturnZeroIfNull(value)); 
      int returnValue = 0; 
      if (iValue != null && iValue != DBNull.Value) 
       returnValue = Convert.ToInt32(iValue); 
      return returnValue; 
     } 


     /// <summary> 
     /// ConvertToLong ---This function is used to convert object to Long 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     private static long ConvertToLong(object lngValue) 
     { 
      //return Convert.ToInt64(HelperFunctions.ReturnZeroIfNull(value)); 
      Int64 returnValue = 0; 
      if (lngValue != null && lngValue != DBNull.Value) 
       returnValue = Convert.ToInt64(lngValue); 
      return returnValue; 
     } 

     /// <summary> 
     /// ConvertToDecimal --- This function is used to convert object to Decimal 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     private static decimal ConvertToDecimal(object decValue) 
     { 
      //return Convert.ToDecimal(HelperFunctions.ReturnZeroIfNull(value)); 
      decimal returnValue = 0; 
      if (decValue != null && decValue != DBNull.Value) 
       returnValue = Convert.ToDecimal(decValue); 
      return returnValue; 
     } 


     /// <summary> 
     /// DateTime --- This function is used to convert object to convertToDateTime 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     private static DateTime? convertToDateTime(object dtValue) 
     { 
      // return Convert.ToDateTime(HelperFunctions.ReturnDateTimeMinIfNull(date)); 
      DateTime? returnValue = null; 
      if (dtValue != null && dtValue != DBNull.Value) 
       returnValue = Convert.ToDateTime(dtValue); 
      return returnValue; 
     } 



     /// <summary> 
     /// ConvertToBool ---This function is used to convert object to Bool 
     /// </summary> 
     /// <param name="sender"></param> 
     /// <param name="e"></param> 

     private static bool ConvertToBool(object blValue) 
     { 
      //return Convert.ToDecimal(HelperFunctions.ReturnZeroIfNull(value)); 
      bool returnValue = false; 
      if (blValue != null && blValue != DBNull.Value) 
       returnValue = Convert.ToBoolean(blValue); 
      return returnValue; 
     } 
     #endregion ConvertToList 

方法2 - 從手動映射像下面

手冊映射到對象從數據表建模。在這種方法中,我們需要爲每個映射編寫這種方法。

List<Student> studentList = new List<Student>(); 
for (int i = 0; i < dt.Rows.Count; i++) 
{ 
    Student student = new Student(); 
    student.StudentId = Convert .ToInt32 (dt.Rows[i]["StudentId"]); 
    student.StudentName = dt.Rows[i]["StudentName"].ToString(); 
    student.Address = dt.Rows[i]["Address"].ToString(); 
    student.MobileNo = dt.Rows[i]["MobileNo"].ToString(); 
    studentList.Add(student); 
} 

我的問題 -在轉換的這種通用的方式使得對性能的影響?我是否應該切換到像方法2之類的對象的正常手動映射?是方法2增強性能?

+1

當然,它會影響性能。你應該決定這種影響在你的情況下是否可以接受。你也可以使用面向性能的ORM(比如Dapper),它會爲你做動態轉換(並且最可能比所提供的代碼示例更好)。 – Evk

+0

通過反射訪問所有內容可能會慢很多,是的。在你的應用程序中這是否意義重大是另一回事。請注意,已經有很多映射庫可用 - 我猜想其中一個可以滿足您的需求,而且它們可能比您當前的代碼更加優化。 –

+0

你可以嘗試使用AutoMapper(http://automapper.org/) –

回答

1

回答是/否不準確。

你需要做的是測量數字。我建議使用像dotTrace這樣的性能測量工具。

  1. 創建測試用例,用於映射包含許多行的單個表,多個小型表和包含許多列的表。
  2. 的基於反射的泛型方法和人工方法

運行基準這將使你有多少時間你正在使用手動映射什麼殊榮和準確的數字是泛型方法的瓶頸。

如果你的勝利很小(可以說10-20%的時間)或者只在特定情況下工作,那麼使用手動映射是不值得的。

此外,它可以幫助你發現你的通用方法的弱點。例如,發現財產

PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance); 

可能會移動一級並移動到散列表。發現每一行的屬性可能是矯枉過正的。

相關問題