C # Database Mapper

#c# #orm #dapper

#c# #orm #dapper

Вопрос:

Я хотел сопоставить результаты запроса к базе данных с объектами строгого типа в моем коде c #. Итак, я написал быстрый и грязный вспомогательный метод для класса SqlConnection, который запускает запрос к базе данных и использует отражение для сопоставления столбцов записей со свойствами объекта. Код приведен ниже:

  public static T Query<T>(this SqlConnection conn, string query) where T : new()
    {
        T obj = default(T);

        using (SqlCommand command = new SqlCommand(query, conn))
        {
            using (SqlDataReader reader = command.ExecuteReader())
            {
                while (reader.Read())
                {
                    obj = new T();

                    PropertyInfo[] propertyInfos;
                    propertyInfos = typeof(T).GetProperties();

                    for (int i = 0; i < reader.FieldCount; i  )
                    {
                        var name = reader.GetName(i);

                        foreach (var item in propertyInfos)
                        {
                            if (item.Name.Equals(name, StringComparison.InvariantCultureIgnoreCase) amp;amp; item.CanWrite)
                            {
                                item.SetValue(obj, reader[i], null);
                            }
                        }

                    }
                }
            }
        }

        return obj;
    }
 

   public class User
    {
        public int id { get; set; }
        public string firstname { get; set; }
        public string lastname { get; set; }
        public DateTime signupDate { get; set; }
        public int age { get; set; }
        public string gender { get; set; }
    }


   var user = conn.Query<User>("select id,firstname,lastname from users");      
 

Я просто хотел услышать второе мнение о моем подходе к использованию отражения для объединения значений, если есть что-то, что я могу сделать лучше в приведенном выше коде. Или, если есть какой-то другой совершенно другой подход, который я могу использовать, чтобы получить тот же результат?

Я думаю, что, вероятно, смогу улучшить код в вспомогательном методе, удалив цикл для propertyInfos и используя вместо него словарь. Есть ли что-нибудь еще, что нужно настроить?

P.S: я знаю о Dapper, я просто хотел реализовать что-то подобное самостоятельно, чтобы помочь мне лучше учиться.

Ответ №1:

То, что вы сделали, — это в основном то, что linq-to-sql или другие OR-mappers делают под капотом. Чтобы узнать подробности о том, как это работает, всегда полезно написать что-то с нуля.

Если вы хотите больше вдохновения или хотите иметь что-то готовое для использования в производстве «из коробки», я бы рекомендовал ознакомиться с linq-to-sql. Он легкий, но компетентный.

Комментарии:

1. Спасибо, Андерс, я уже некоторое время использую linq-to-sql, но я хотел, чтобы что-то просто работало с POCOs, и я хотел, чтобы производительность была как можно ближе к родной ADO.NET . Мне также надоело изучать новые реализации, которые Microsoft предлагает нам, LINQ2SQL, Entity… только для того, чтобы спустя несколько месяцев обнаружить, что они переходят к чему-то новому, потому что их последнее предложение работает не так хорошо.

Ответ №2:

Есть несколько вещей, о которых я могу думать:

  1. Я думаю, что для того, чтобы пропустить цикл, вы можете использовать:
     reader[item.Name]
     
  2. Я сам делал что-то подобное, но я никогда не сталкивался с dapper. Я не уверен, использует ли он отражение, но всегда полезно прочитать чужой код, чтобы отточить свои навыки (Скотт Хансельман часто рекомендует это делать).
  3. Вы также можете посмотреть: http://www.codeproject.com/KB/database/metaquery_part1.aspx
  4. Вы можете реализовать атрибут, который сопоставляет поле со столбцом базы данных, но это просто для развлечения.

Редактировать:

5. Вы также можете пропустить цикл while над программой чтения и просто взять первую строку и задокументировать тот факт, что ваш запрос возвращает только один объект, поэтому он не извлекает тысячу строк, если запрос возвращает тысячу строк.

Комментарии:

1. Dapper не использует отражение, а скорее компилирует код для гораздо более быстрого выполнения. Кстати: Dapper используется здесь в Stackoverflow. А для получения дополнительной информации ознакомьтесь с Dapper, PetaPoco и Massive; все три представляют собой библиотеки данных с одним файлом micro ORM .

2. да, я узнал в ходе своего тестирования, что SetValu — это реальная проблема с производительностью, когда я использовал секундомер для определения времени производительности, теперь я пытаюсь узнать об использовании IL для повышения производительности. Да, я знаю о dapper, sam saffron и о том, как он используется в производстве на SO itself. Я также немного читал о PetaPoco, мне это тоже нравится — это именно то, что мне самому было нужно. Я просто подумал, что вместо того, чтобы брать эти готовые к использованию библиотеки, почему бы просто не попробовать сделать это самостоятельно и узнать несколько вещей по пути, тем более, что все они сами по себе являются реализациями одного файла.