2013-09-21 4 views
2

Итак, у меня есть приложение, которое находится в базе данных. До сих пор результаты моих запросов пошли все в DataTable объекта, как это:Как эффективно создать список объектов внутри универсального метода?

DataTable data = new DataTable(); 
data.Load(someQuery.ExecuteReader()); 

Теперь я хочу, чтобы загрузить свои данные в список сильно типизированных объектов. Что-то вроде этого:

List<MyClass> data = someQuery.Load<MyClass>(); 

Однако мой первый взгляд на написание этого метода в конечном итоге работает почти в три раза медленнее, чем метод DataTable.Load (IDataReader). В принципе, у меня есть пользователь GetConstructor (null) .Invoke (null) для создания и объекта, и я использовал PropertyInfo.SetValue (reader.GetValue()), чтобы заполнить его данными.

Есть ли лучший способ сделать это?

Метод, используемый:

public List<T> LoadData<T>(DbCommand query) 
    { 
     Type t = typeof(T); 

     List<T> list = new List<T>(); 
     using (IDataReader reader = query.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       T newObject = (T)t.GetConstructor(null).Invoke(null); 

       for (int ct = 0; ct < reader.FieldCount; ct++) 
       { 
        PropertyInfo prop = t.GetProperty(reader.GetName(ct)); 
        if (prop != null) 
         prop.SetValue(newObject, reader.GetValue(ct), null); 
       } 

       list.Add(newObject); 
      } 
     } 

     return list; 
    } 
+0

Отражение, без сомнения, медленное. При строго типизированном вы всегда подразумеваете 'MyClass', или может быть любой тип say' T'? Можете ли вы отправить код для загрузки в список сильно типизированных объектов? –

+0

Любой класс может быть использован. Свойства класса должны соответствовать данным, конечно. – Nezreli

ответ

1

Для этого эффективно требует метапрограммирование. Вы можете использовать библиотеки, чтобы помочь. Например, «FastMember» включает TypeAccessor, который обеспечивает быстрый доступ к созданию экземпляра и доступа к члену по имени. Однако этот пример также, в основном, как именно «щеголеватый» работает, так что вы можете просто использования Dapper:

int id = ... 
var data = connection.Query<Order>(
    "select * from Orders where CustomerId = @id", 
    new { id }).ToList(); 

Вы также можете открыть «щеголеватый» код, чтобы увидеть, что он делает.

+0

Никогда не знал, что он существует. Автор утверждает, что скорость, я попробую проверить. – Nezreli

+0

@Nezreli да, я требую скорость :) мы написали dapper здесь, в Stack Exchange, в частности, с показателем эффективности. Мы оптимизировали его, пока он не скрипел, в основном - потому что мы «довольно много» доступа к данным. –

+0

Спасибо. Я столкнулся с таблицей 300M +. Мне нужна вся помощь, с которой я смогу справиться. – Nezreli

0

Вы можете выполнить запрос с помощью Linq и получить список Generic, а затем, если вы хотите CONVER его DataTable, используйте следующий код, он может помочь вам.

public DataTable ListToDataTable<T>(IEnumerable<T> list) 
    { 
     PropertyDescriptorCollection properties = 
      TypeDescriptor.GetProperties(typeof(T)); 
     DataTable table = new DataTable(); 
     foreach (PropertyDescriptor prop in properties) 
      table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType); 
     foreach (T item in list) 
     { 
      DataRow row = table.NewRow(); 
      foreach (PropertyDescriptor prop in properties) 
       row[prop.Name] = prop.GetValue(item) ?? DBNull.Value; 
      table.Rows.Add(row); 
     } 
     return table; 
    } 

он будет работать для любого типа типа. Проверьте время, необходимое для выполнения.

Спасибо,

+1

Я не думаю, что OP хочет использовать DataTable здесь вообще ... –

Смежные вопросы