Общий метод. Присвоение свойств из DataReader универсальным объектам - PullRequest
1 голос
/ 05 ноября 2010

Доброе утро, я создал свой первый общий метод, собранный из набора Google Searches. Я хотел бы, чтобы кто-то просмотрел это и дал мне знать, нарушаю ли я какие-либо основные правила или есть способы улучшить этот метод.

Метод вызывает хранимую процедуру в 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 ]

1 голос
/ 05 ноября 2010

Хотя этот подход работает, вы определенно захотите добавить некоторую обработку ошибок.

Существуют также библиотеки, которые могут сделать это за вас, например AutoMapper .Вы также можете посмотреть на другие ORM, такие как SubSonic, Linq2SQL, EntityFramework, NHibernate и т. Д. *

Также обратите внимание, что рефлексия очень медленная, особенно повторяя ее снова и снова.Если это будет в большой корпоративной системе с большой нагрузкой, вам лучше будет сгенерировать динамический метод и ИТ-код, чтобы выполнить сопоставление при первом обнаружении сопоставления, а затем повторно запускать один и тот же динамический метод снова и снова.вместо того, чтобы полагаться на рефлексию.

1 голос
/ 05 ноября 2010

Я не знаю, буду ли я это делать или нет. Я бы сначала использовал ORM, например Entity Framework. Я сделал что-то похожее на это в прошлом, но есть некоторые недостатки:

  • Отражение может быть медленнее, чем просто указывать все, от чего зависит, и это может вообще не быть для вас проблемой.
  • Большая проблема для меня заключается просто в том, что вы рискуете больше ошибок времени выполнения, а не ошибок времени компиляции, поэтому экономите время заранее, но в долгосрочной перспективе это может привести к досадным ошибкам.

О единственной вещи, которую я определенно скажу сделать, - это обязательно использовать try / catch / finally, try / finally или обернуть SqlConnection, SqlCommand и SqlDataReader внутри using (). Я просто потратил 2 дня на рефакторинг, потому что предыдущие разработчики не закрывали ни одного соединения или устройства чтения данных, а пул соединений разрывал и отказывал в соединениях.

...