将数据表转换为列表<t>(模型类列表)通用方法性能

时间:2017-06-22 10:26:30

标签: c# entity-framework generics ado.net

我正在使用ADO.NET over Entity Framework来获得高性能,因为我的应用程序的数据复杂性有点高。因此与以下两种方法相混淆:

方法1 - 通用方法适用于所有

我使用下面的通用方法将数据表转换为适当的模型对象。在这里,它使用反射并匹配模型的所有属性和数据表头,用于映射和构建适当的列表。

    @Override
    public void insertUpdate(DocumentEvent e) {
        fieldList.put(field,getText());
    }

    @Override
    public void removeUpdate(DocumentEvent e) {
        fieldList.put(field,getText());
    }

方法2 - 通过下面的手动映射

从数据表手动映射到模型对象。在这种方法中,我们需要为每个映射编写此方法。

#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 等对象的正常手动映射吗?是方法2 提升绩效?

1 个答案:

答案 0 :(得分:1)

回答是/否不准确。

您需要做的是衡量数字。我建议使用dotTrace等性能测量工具。

  1. 创建用于映射具有许多行的单个表的测试用例,许多小表和具有许多列的表。
  2. 运行基于反射的通用和手动方法的基准
  3. 这将为您提供使用手动映射赢得多少时间的精确数字以及通用方法的瓶颈。

    如果您的胜利很小(比如10-20%的时间)或仅在特定情况下有效,那么使用手动映射是不值得的。

    它也可以帮助您发现通用方法的弱点。例如,发现属性

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

    可以向上移动一级并移动到哈希表。发现每行的属性可能有点过分。