2012-11-14 27 views
0

反對我有這樣數據表通過使用反射和LINQ

Name| Value 
----|------ 
NA | VA 
NB | VB 
NC | VC1 
NC | VC2 
ND | VD1 
ND | VD2 

一個數據表和一類這樣

Class NVMapping { 
    List<string> NC { get; set; } 
    List<string> ND { get; set; } 
    string NA { get; set; } 
    string NB { get; set; } 
} 

如何使用LINQ或其他方式向數據錶轉移到這種類型的?

我想我需要在這裏強調一件事。這種映射在我的應用程序中會有很多。

不知何故,我認爲使用反射可以使這個函數是通用的,以處理所有這些有點映射。

所以如果可能的話,我寧願像通過反射來實現這個功能。

如果可能的話,將數據錶轉換成上述轉換等對象會更好。

謝謝!

回答

5

可能我建議編寫一個使用反射的通用方法。以下方法使用反射來從DataTable中的DataRow填充類的公共屬性(或類的列表,其中一個來自DataTable中的每個DataRow),其中ColumnName完全匹配類中公共屬性的名稱(case -敏感)。 如果DataTable有多餘的列與類中的某個屬性不匹配,則會忽略它們。如果DataTable缺少與類屬性相匹配的列,那麼該屬性將被忽略並保留爲該類型的默認值(因爲它是屬性)。

 
    public static IList<T> DatatableToClass<T>(DataTable Table) where T : class, new() 
    { 
     if (!Helper.IsValidDatatable(Table)) 
      return new List<T>(); 

     Type classType = typeof(T); 
     IList<PropertyInfo> propertyList = classType.GetProperties(); 

     // Parameter class has no public properties. 
     if (propertyList.Count == 0) 
      return new List<T>(); 

     List<string> columnNames = Table.Columns.Cast<DataColumn>().Select(column => column.ColumnName).ToList(); 

     List<T> result = new List<T>(); 
     try 
     { 
      foreach (DataRow row in Table.Rows) 
      { 
       T classObject = new T(); 
       foreach (PropertyInfo property in propertyList) 
       { 
        if (property != null && property.CanWrite) // Make sure property isn't read only 
        { 
         if (columnNames.Contains(property.Name)) // If property is a column name 
         { 
          if (row[property.Name] != System.DBNull.Value) // Don't copy over DBNull 
          { 
           object propertyValue = System.Convert.ChangeType(
             row[property.Name], 
             property.PropertyType 
            ); 
           property.SetValue(classObject, propertyValue, null); 
          } 
         } 
        } 
       } 
       result.Add(classObject); 
      } 
      return result; 
     } 
     catch 
     { 
      return new List<T>(); 
     } 
    } 

如果你有興趣在走另一條路,並填寫從一個類的公共屬性的DataTable,我覆蓋和更多的在我的C#的博客,CSharpProgramming.tips/Class-to-DataTable

3

這就是:

IEnumerable<DataRow> rows = table.AsEnumerable(); 
string naValue = null; 
var naRow = rows.FirstOrDefault(r => r.Field<string>("Name") == "NA"); 
if(naRow != null) 
    naValue = naRow.Field<string>("Value"); 
string nbValue = null; 
var nbRow = rows.FirstOrDefault(r => r.Field<string>("Name") == "NB"); 
if(nbRow != null) 
    nbValue = nbRow.Field<string>("Value"); 
NVMapping map = new NVMapping { 
    NC = rows.Where(r => r.Field<string>("Name") == "NC") 
     .Select(r => r.Field<string>("Value")).ToList(), 
    ND = rows.Where(r => r.Field<string>("Name") == "ND") 
     .Select(r => r.Field<string>("Value")).ToList(), 
    NA = naValue, 
    NB = nbValue 
};