C# 将数据表转换为列表(模型类列表)通用方法性能
我使用ADO.NET over Entity Framework来获得高性能,因为我的应用程序的数据复杂性有点高。因此与以下两种方法混淆: 方法1-适用于所有人的通用方法 我使用下面的通用方法将数据表转换为适当的模型对象。在这里,它使用反射并将模型的所有属性与映射和构建适当列表的数据表头相匹配C# 将数据表转换为列表(模型类列表)通用方法性能,c#,entity-framework,generics,ado.net,C#,Entity Framework,Generics,Ado.net,我使用ADO.NET over Entity Framework来获得高性能,因为我的应用程序的数据复杂性有点高。因此与以下两种方法混淆: 方法1-适用于所有人的通用方法 我使用下面的通用方法将数据表转换为适当的模型对象。在这里,它使用反射并将模型的所有属性与映射和构建适当列表的数据表头相匹配 #region ConvertToList /// <summary> /// DataTableToList --- This function is us
#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等对象的常规手动映射?方法2是否提高了性能 回答是/否并不准确 你需要做的是测量数字。我建议使用dotTrace之类的性能度量工具 创建用于映射具有多行的单个表、多个小表和多个列的表的测试用例。 运行基于反射的通用和手动方法的基准测试 这将为您提供使用手动映射赢得多少时间的精确数字,以及泛型方法的瓶颈是什么 如果您的胜利很小,比如说10-20%的时间或者只在特定情况下有效,那么使用手动映射就不值得努力 它还可以帮助您发现通用方法的弱点。例如发现财产
PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
可以向上移动一级并移动到哈希表。发现每一行的属性可能有些过分 确保它对性能产生影响。你应该决定这种影响在你的情况下是否可以接受。您还可以使用面向性能的ORM,如Dapper,它将为您进行动态转换,并且很可能比提供的代码示例要好得多。这在您的应用程序中是否重要是另一回事。请注意,已经有很多映射库可用-我怀疑其中一个可以满足您的需要,并且它们可能比您当前的代码优化得多。您可以尝试使用AutoMapper
PropertyInfo propertyInfos = classObj.GetType().GetProperty(dtField.Name, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);