2009-02-13 15 views
6
public static IList<T> ConvertTo<T>(DataTable table) 
    { 
     if (table == null) 
     { 
      return null; 
     } 

     List<DataRow> rows = new List<DataRow>(); 

     foreach (DataRow row in table.Rows) 
     { 
      rows.Add(row); 
     } 

     return ConvertTo<T>(rows); 
    } 

    public static T ConvertItem<T>(DataTable table) 
    { 
     T obj = default(T); 
     if (table != null && table.Rows.Count > 0) 
     { 
      obj = CreateItem<T>(table.Rows[0]); 
     } 
     return obj; 
    } 


    public static T CreateItem<T>(DataRow row) 
    { 
     T obj = default(T); 
     if (row != null) 
     { 
      obj = Activator.CreateInstance<T>(); 
      Type entityType = typeof(T); 
      PropertyInfo[] properties = entityType.GetProperties(); 

      for (int i = 0; i < properties.Length; i++) 
      { 
       object[] customAttributes = properties[i].GetCustomAttributes(typeof(ColumnAttributes), false); 
       ColumnAttributes dataField = null; 
       if (null != customAttributes && customAttributes.Length > 0 && null != (dataField = customAttributes[0] as ColumnAttributes)) 
       { 
        if (row.Table.Columns.Contains(dataField.FieldName) && !row[dataField.FieldName].GetType().FullName.Equals("System.DBNull")) 
        { 
         properties[i].SetValue(obj, row[dataField.FieldName], null); 
        } 
       } 
      } 
     } 
     return obj; 
    } 

To, co teraz możemy sobie tylko wyobrazić, to że musimy robić coś, co musimy zebrać śmieci?Konwertuj DataTable na ogólną listę?

Myśli?

Dlaczego uważamy, że może być przeciek ?:

Jesteśmy wstanie z błędami pamięci. Jeśli strona nie wymaga logiki biznesowej do użycia tego typu konwersji, proces II6 nie rośnie, ale kiedy trafimy na stronę, która z niego korzysta, rośnie.

Aktualnie otrzymujemy program ANTS Profiler, aby przekazać nam więcej informacji.

+0

co świadczy o przecieku masz? –

+0

Gdzie jest dokładnie ten problem? –

+0

U ywasz nHIbernate? – renegadeMind

Odpowiedz

9

To nie będzie rzeczywiste wyciek, ale może to być podkreślając rzeczy niepotrzebnie ...

Ile wierszy pracujesz nad? Zauważ, że odbicie jest bólem, a każde wezwanie do rzeczy takich jak GetCustomAttributes może zwrócić nową tablicę (więc chcesz to zrobić raz, a nie raz na właściwość na wiersz).

Osobiście wstępnie skonstruowałem pracę, którą zamierzam wykonać ... coś jak poniżej.

Zauważ, że gdybym robił tę partię, albo przestawiłbym się na HyperDescriptor, albo gdyby .NET 3.5 była opcją, może skompilowanym wyrażeniem. Od DataTable nie jest silnie wpisany, HyperDescriptor byłby logiczny następny krok (dla wydajności) po niżej ...

sealed class Tuple<T1, T2> 
{ 
    public Tuple() {} 
    public Tuple(T1 value1, T2 value2) {Value1 = value1; Value2 = value2;} 
    public T1 Value1 {get;set;} 
    public T2 Value2 {get;set;} 
} 
public static List<T> Convert<T>(DataTable table) 
    where T : class, new() 
{ 
    List<Tuple<DataColumn, PropertyInfo>> map = 
     new List<Tuple<DataColumn,PropertyInfo>>(); 

    foreach(PropertyInfo pi in typeof(T).GetProperties()) 
    { 
     ColumnAttribute col = (ColumnAttribute) 
      Attribute.GetCustomAttribute(pi, typeof(ColumnAttribute)); 
     if(col == null) continue; 
     if(table.Columns.Contains(col.FieldName)) 
     { 
      map.Add(new Tuple<DataColumn,PropertyInfo>(
       table.Columns[col.FieldName], pi)); 
     } 
    } 

    List<T> list = new List<T>(table.Rows.Count); 
    foreach(DataRow row in table.Rows) 
    { 
     if(row == null) 
     { 
      list.Add(null); 
      continue; 
     } 
     T item = new T(); 
     foreach(Tuple<DataColumn,PropertyInfo> pair in map) { 
      object value = row[pair.Value1]; 
      if(value is DBNull) value = null; 
      pair.Value2.SetValue(item, value, null); 
     } 
     list.Add(item); 
    } 
    return list;   
} 
+0

dziękuję zajrzą to :) – TimLeung

+0

Zgadzam się z Markiem. Twój kod jest powolny i dość skomplikowany! Powinieneś również sprawdzić typy właściwości, aby nie próbować ustawiać wartości int na wartość łańcucha i tak dalej. –