通用方法。将属性从DataReader分配给通用对象

时间:2010-11-05 18:25:07

标签: c# generics methods class-design

早上好,我已经创建了我的第一个通用方法拼接在一起的谷歌搜索。我希望有人看一下,如果我违反任何主要规则或者有办法改进这种方法,请告诉我。

该方法在sql中调用存储过程,然后使用反射根据从DataReader架构读取的值分配属性。对存储过程进行编码,以便它们返回类所期望的确切属性名称。这是代码:

       public static List<T> GetList<T>(string SQLServer, string DBName,
        string ProcedureName, Dictionary<string, string> Parameters )
         where T : new()
    {
        List<T> list = new List<T>();

        //Setup connection to SQL
        SqlConnection SqlConn = new SqlConnection(ConnectionString(SQLServer, DBName));
        SqlCommand SqlCmd = new SqlCommand(ProcedureName, SqlConn);
        SqlCmd.CommandType = System.Data.CommandType.StoredProcedure;
        SqlDataReader reader;

        //Process Parameters if there are any
        foreach (KeyValuePair<string, string> param in Parameters)
        {
            SqlCmd.Parameters.AddWithValue(param.Key, param.Value);
        }

        SqlConn.Open();
        reader = SqlCmd.ExecuteReader();

        //Get The Schema from the Reader
        //The stored procedure has code to return
        //the exact names expected by the properties of T
        DataTable schemaTable = reader.GetSchemaTable();
        List<string> fields = new List<string>();
        foreach (DataRow r in schemaTable.Rows)
        {
            fields.Add(r[0].ToString());
        }


        while (reader.Read())
        {
            T record = new T();

            foreach (string field in fields)
            {
                //Assign the properties using reflection
                record.GetType().GetProperty(field).SetValue(
                    record, reader[field],
                    System.Reflection.BindingFlags.Default,
                    null,null,null);
            }

            list.Add(record);
        }
        return list;
    }

2 个答案:

答案 0 :(得分:1)

我不知道这是不是我做过的事。我可能会首先使用ORM,例如实体框架。我做了类似于过去的事情,但也有一些缺点:

  • 反思可能比指定所有内容更慢,取决于多少,而且根本不是问题。
  • 对我来说更大的问题只是冒着更多的运行时错误而不是编译错误的风险,因此可以预先节省时间,但从长远来看可能会引入烦人的错误。

关于我唯一要做的就是确保使用try / catch / finally,try / finally,或者在using()s中包装SqlConnection,SqlCommand和SqlDataReader。我只花了2天时间进行重构,因为之前的开发人员没有关闭任何连接或datareader,连接池正在爆炸并拒绝连接。

答案 1 :(得分:1)

虽然这种方法确实有效,但您肯定希望添加一些错误处理。

还有现有的库可以为您完成此操作,例如AutoMapper。您还可以查看其他ORM,如SubSonic,Linq2SQL,EntityFramework,NHibernate等......

另请注意,反射非常慢,特别是反复这样做。如果这将是一个大型企业重负载系统,你最好生成ta动态方法和IT代码,以便在第一次遇到映射时进行映射,然后一遍又一遍地重新运行相同的动态方法而不是依赖于反思。