如何优化此代码?

时间:2009-11-10 18:31:12

标签: c# reflection datatable

我有一个方法,它实质上将数据表转换为我称之为“包”的对象列表。每个会话多次调用此代码,许多会话同时运行,有时会有数千行。因此,我需要尽可能快。我有一个xml文件,其中包含DataColumn到Property映射。优化的主要方法是ConvertRowToBag - 传入的类型参数是从BagBase派生的类型。

这是一长串代码,但任何提示都会非常感激。

public class BagBase
{
    /// <summary>
    /// Dictionary of properties and names
    /// </summary>
    private static Dictionary<string, PropertyInfo> propertyDictionary = new Dictionary<string, PropertyInfo>();

    /// <summary>
    /// Table of column/property mappings
    /// </summary>
    private static DataTable mappings = new DataTable("Mappings");

    /// <summary>
    /// Returns true if the map exists
    /// </summary>
    /// <param name="columnName"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    private static bool MappingExists(string columnName, Type type)
    {
        DataRow [] rows = BagBase.mappings.Select(String.Format("Type = '{0}' and ColumnName = '{1}'", type.Name, columnName));
        return (rows != null && rows.Length > 0);
    }

    /// <summary>
    /// Converts the table to bags.
    /// </summary>
    /// <param name="table">The table.</param>
    /// <param name="outputType">Type of the output.</param>
    /// <returns></returns>
    protected static List<BagBase> ConvertTableToBags(DataTable table, Type outputType)
    {
        Trace.TraceInformation(String.Format("ConvertTableToBags : table={0} Type={1}", table.TableName, outputType.Name));

        // Create an empty list
        List<BagBase> result = new List<BagBase>();

        // Iterate through the rows
        foreach (DataRow row in table.Rows)
        {
            // Add to the list
            result.Add(ConvertRowToBag(outputType, row));
        }

        Trace.TraceInformation("ConvertTableToBags Finished.");

        return result;
    }

    /// <summary>
    /// Converts the row to bag.
    /// </summary>
    /// <param name="outputType">Type of the output.</param>
    /// <param name="row">The row.</param>
    /// <returns></returns>
    protected static BagBase ConvertRowToBag(Type outputType, DataRow row)
    {
        // Create an instance of the child class and store in the base
        BagBase bag = Activator.CreateInstance(outputType) as BagBase;

        // Iterate through the columns
        foreach (DataColumn column in row.Table.Columns)
        {
            // If this column has been mapped
            if (BagBase.MappingExists(column.ColumnName, outputType))
            {
                PropertyInfo property;

                string columnProperty = String.Format("{0}={1}", column.ColumnName, outputType.Name);

                // Get the property as defined in the map
                if (!propertyDictionary.ContainsKey(columnProperty))
                {
                    // Get the property
                    property = outputType.GetProperty(BagBase.GetColumnMapping(column.ColumnName, outputType));

                    // Add the property to the dictionary
                    propertyDictionary.Add(columnProperty, property);
                }
                else
                {
                    property = propertyDictionary[columnProperty];
                }

                if (property != null)
                {
                    if (!row.IsNull(column))
                    {
                        // Set the value to the in the table
                        if (property.PropertyType.BaseType != null && property.PropertyType.BaseType == typeof(Enum))
                        {
                            if (column.DataType != typeof(String))
                            {
                                property.SetValue(bag, Enum.ToObject(property.PropertyType, row[column]), null);
                            }
                            else
                            {
                                property.SetValue(bag, Enum.ToObject(property.PropertyType, Convert.ToChar(row[column])), null);
                            }
                        }
                        else if (property.PropertyType == typeof(DateTime?))
                        {
                            property.SetValue(bag, (DateTime?)row[column], null);
                        }
                        else
                        {
                            property.SetValue(bag, Convert.ChangeType(row[column], property.PropertyType), null);
                        }
                    }
                    else // No nulls
                    {
                        if (column.DataType == typeof(String))
                        {
                            property.SetValue(bag, String.Empty, null);
                        }
                    }

                    // Generate the unique class.property name
                    string propertyKey = String.Format("{0}.{1}", outputType.Name, property.Name);
                    if (!columnCaptions.ContainsKey(propertyKey))
                    {
                        // Add to the caption map
                        columnCaptions.Add(propertyKey, column.Caption);
                    }
                }
            }
            else
            {
                // If this column isn't mapped, add it to Other information
                if (bag.OtherInformation == null)
                {
                    bag.OtherInformation = new Dictionary<string, string>();
                }

                bag.OtherInformation.Add(column.ColumnName, !row.IsNull(column) ? row[column].ToString() : String.Empty);
            }
        }

        return bag;
    }
}

2 个答案:

答案 0 :(得分:5)

使用分析器。我们无法知道代码中实际花费的时间是多少。

尝试逐行优化并没有用,很多人似乎都不知道这一点。计算机总是在等待资源,有时它是CPU或磁盘IO,而且通常是用户。要使任何代码更快,请使用分析器找到瓶颈,并努力使代码更快。

答案 1 :(得分:2)

除了“使用分析器”的一般建议之外,可能没有一个瓶颈,但是一系列慢速调用或者过程的结构正在创建不必要的迭代。一目了然:

  • 针对数据表的选择通常不是很有效。
  • 反思带来了很多开销,看起来你依赖它,但如果你可以限制它的范围,你可能会获得更好的整体性能。