关于优化C#代码的建议

时间:2011-05-19 11:21:28

标签: c#

我编写了一个通用的数据库帮助方法,它返回特定实体的记录。

这是我如何做到的:

  • 我有一个名为Customer的类,它有10个属性,还有一个名为TableName的属性。

  • 有一个方法只接受Type参数,并返回一个传递类型的数组。

  • 该方法的工作原理是,通过使用反射得到一个表名,然后触发一个select语句,并在DataReader的基础上循环遍历每个列和传递的Type的属性。

所以,问题是假设有100万条记录和10个属性。它循环10(属性)*(1,000,000条记录)= 10,000,000次

是否有任何优化的方法来执行此操作,例如对阵Datareader使用LINQ?

这是一个代码

object[] LoadAll(Type type)
    {

        try
        {
            object obj = Activator.CreateInstance(type);
            SqlConnection conn = new SqlConnection("connection string");
            string tableName = type.GetField("TableName").GetValue(obj) as string;
            SqlCommand cmd = conn.CreateCommand();
            cmd.CommandText = string.Format("select * from {0}", tableName);
            conn.Open();
            List<object> list = new List<object>();
            SqlDataReader reader = cmd.ExecuteReader();

            while (reader.Read())
            {
                object obj1 = Activator.CreateInstance(type);
                foreach (PropertyInfo propertyInfo in type.GetProperties())
                {
                    obj.GetType().GetProperty(propertyInfo.Name).SetValue(obj1,reader[propertyInfo.Name],null);
                }

                list.Add(obj1);
            }


        }

感谢名单

6 个答案:

答案 0 :(得分:1)

尝试像NHibernate这样的对象关系映射器。

答案 1 :(得分:0)

听起来您正在计算实体的每个实例的大小。您应该有一些元数据控制器来缓存每个表名的实体大小。假设我理解你的问题,对于相同的表名,大小将始终相同。

答案 2 :(得分:0)

如果我正确地解决了问题,听起来你可以简单地让DB为你工作。你说“然后触发一个选择语句”:你能不能发出一个更聪明的选择语句来执行你要解释的内容吗?

当你说你正在遍历每一栏时,我并不完全明白你要做什么。但请查看“Group by”和“aggrop”又名“Aggregate operators”,看看是否有任何一个可以帮助你。

答案 3 :(得分:0)

从优化的角度来看,没有必要为100万条记录维护与db的连接,这意味着在循环结束之前,你正在与数据库进行交互。 :(。 为了优化,您将整个表记录缓存在某个数据集中,然后迭代它。不要长时间连接到数据库。希望这将是你的问题的答案。 :)

答案 4 :(得分:0)

你可能会稍微收紧一下环以减少涉及反射的调用。您无需创建该初始obj

PropertyInfo[] properties = type.GetProperties();
while (reader.Read())
{
    object obj = Activator.CreateInstance(type);
    foreach (PropertyInfo propertyInfo in properties)
    {
        propertyInfo.SetValue(obj, reader[propertyInfo.Name], null);
    }
    list.Add(obj);
}

但要更快地获得它,你可以通过LoadAll()函数传递一种方法将行映射到一个新对象,类似于:

IEnumerable<T> LoadAll<T>(Func<DataReader, T> map) {
    var tablename = typeof(T).GetField("TableName)......
    // other connection and query stuff
    while (reader.Read()) {
        yield return map(reader);
    }
}
// use it like:
var kittens = LoadAll<Kitten>(reader => new Kitten {
    Name = (string)reader["Name"],
    Colour = (string)reader["Colour"]
});

这也使您可以更好地控制从数据层到域对象的映射,例如,使用反射的方法需要进行大量修改才能处理enum属性,这样可以直接编写代码一个明确的地图功能。

答案 5 :(得分:-1)

您可以尝试安装 ReSharper 的免费试用版,其检查工具可以提供各种方法来从头开始优化您的代码。