2010-02-17 97 views
5

我有個疑問,有時,我從DataTable這個轉換爲List<T>轉換DataTable中列出<T>

List<EDog> lstDogs = (from drRow in dsDogs.Tables[0].AsEnumerable() 
         select new EDog() 
         { 
          intIdDog = drRow.Field<int>("IdDog"), 
          intIdOwner = drRow.Field<int?>("IdOwner"), 
          intAge = drRow.Field<int>("Age"), 
          strName = drRow.Field<string>("Name") 
         }).ToList(); 

這工作得很好,但我現在想這樣做是通用的,因此,任何類型的DataSet可以轉換爲強類型列表。

我怎麼能使它通用?也許是圍繞這部分並創建對象的代表?

new EDog() 
{ 
    intIdDog = drRow.Field<int>("IdDog"), 
    intIdOwner = drRow.Field<int?>("IdOwner"), 
    intAge = drRow.Field<int>("Age"), 
    strName = drRow.Field<string>("Name") 
} 

我嘗試過,但得到一個錯誤:

select (lambda) expected.... 

什麼建議嗎?

我需要這個的原因是因爲結果中的每個DataRow需要轉換爲實體以便更好地操作。

+0

這是什麼語言? –

+0

C#它似乎...... –

+1

如何將DataTable轉換爲通用列表:http://stackoverflow.com/questions/208532/how-do-you-convert-a-datatable-into-a-通用列表 – sashaeve

回答

6

是這樣的東西你在找什麼?

public static List<T> ConvertDS<T>(DataSet ds, Converter<DataRow, T> converter) 
{ 
    return 
     (from row in ds.Tables[0].AsEnumerable() 
     select converter(row)).ToList(); 
} 
+0

完全一樣,謝謝,那就是我實際做了什麼,然後我逐行地對轉換器方法進行了相反的處理。謝謝你 – lidermin

1

它不會輕易轉換,你可以做,但它可能不會節省很多工作。

想一想代碼示例中的內在知識:知道DataTable中每列的類型和名稱以及它在輸出類型中映射到的屬性的類型和名稱。另一種方法是知道每列的類型和索引(用索引代替名稱)。在這兩種情況下,您都需要定義一個包含該信息的映射。

另一種方法是構建一個基於約定的轉換器 - 換句話說,您的DataTable列名稱及其目標屬性需要一致命名,並且與該約定偏離會導致轉換失敗。

10

好吧,讓我們有一些有趣的:

public static class DataTableExtensions 
{ 
    public static List<T> ToGenericList<T>(this DataTable datatable, Func<DataRow, T> converter) 
    { 
     return (from row in datatable.AsEnumerable() 
       select converter(row)).ToList(); 
    } 
} 

class EDog 
{ 
    private int intIdDog; 
    private int intIdOwner; 
    private int intAge; 
    private string strName; 

    ... 

    public static EDog Converter(DataRow row) 
    { 
     return new EDog 
         { 
          intIdDog = (int)row["IdDog"], 
          intIdOwner = (int)row["IdOwner"], 
          intAge = (int)row["Age"], 
          strName = row["Name"] as string 
         }; 
    } 
} 

用法:

List<EDog> dogs = dsDogs.Tables[0].ToGenericList<EDog>(EDog.Converter); 

但沒有足夠的樂趣,對不對?這個怎麼樣:

class DataRowKeyAttribute : Attribute 
{ 
    private readonly string _Key; 

    public string Key 
    { 
     get { return _Key; } 
    } 

    public DataRowKeyAttribute(string key) 
    { 
     _Key = key; 
    } 
} 


static class DataTableExtensions 
{ 
    public static List<T> ToGenericList<T>(this DataTable datatable) where T : new() 
    { 
     return (from row in datatable.AsEnumerable() 
       select Convert<T>(row)).ToList(); 
    } 

    private static T Convert<T>(DataRow row) where T : new() 
    { 
     var result = new T(); 

     var type = result.GetType(); 

     foreach (var fieldInfo in type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)) 
     { 
      var dataRowKeyAttribute = fieldInfo.GetCustomAttributes(typeof (DataRowKeyAttribute), true).FirstOrDefault() as DataRowKeyAttribute; 
      if (dataRowKeyAttribute != null) 
      { 
       fieldInfo.SetValue(result, row[dataRowKeyAttribute.Key]); 
      } 
     } 

     return result; 
    } 
} 

class EDog 
{ 
    [DataRowKey("IdDog")] 
    private int intIdDog; 
    [DataRowKey("IdOwner")] 
    private int intIdOwner; 
    [DataRowKey("Age")] 
    private int intAge; 
    [DataRowKey("Name")] 
    private string strName; 

    ... 
} 

用法:

List<EDog> dogs = dsDogs.Tables[0].ToGenericList<EDog>(); 

如果你想擁有真正的樂趣,添加錯誤處理,考慮緩存反射數據,以提高性能和改變字段屬性。

-1

我能夠做到這一點的一行代碼: dt是數據表

List<DataRow> alist = new dt.AsEnumerable().ToList(); 
+0

這並沒有回答這個問題。要求是產生一個類型化對象列表(在這種情況下是EDog),而不是DataRow列表。 – Andreas