2012-02-16 95 views
2

我正在嘗試從我的DataTable創建一個字典。目前我通過首先創建一個IList,然後循環遍歷列表並將它們添加到單獨的字典中,逐個指定列表中的結果對象的主鍵屬性。使用泛型和擴展方法將數據錶轉換爲字典<T1,T2>

我想知道這是否可以使用泛型。

香港專業教育學院目前得到了下面的代碼,這犯規編譯或工作:

public static IDictionary<T1, T2> ToDictionary<T1,T2>(this DataTable table) where T2 : new() 
{ 
    IList<PropertyInfo> properties = GetPropertiesForType<T2>(); 
    IDictionary<T1,T2> result = new Dictionary<T1,T2>(); 
    Dictionary<string, int> propDict = GetPropertyDictionary(properties, table); 
    T1 PK; 
    foreach (var row in table.Rows) 
    { 
     var item = CreateDictItemFromRow<T2>((DataRow)row, properties, propDict); 
     result.Add(item. item); //not sure here 
    } 
    return result; 
} 

基本上我想調用如下

Dictionary<int, MyDBClass> Items = DataTable.ToDictionary<int,MyDBClass>(); 

Dictionary<Int16,MyDBClass> Items = DataTable.ToDictionary<Int16, MyDBClass>(); 

林假設某處我需要將主鍵屬性名稱傳遞給此函數。否則,我可以安全地假設我的Datatable中的第一列包含主鍵(儘管假設它始終是一個int(它可能是一個短字節或字節))並不安全。

我也明白這可以很容易地使用LINQ完成,但我沒有得到那麼遠的C#,並希望改變現有的應用程序。

幫助表示讚賞。

+0

有一個與你問什麼,怎麼會是可能的,如果數據表有更多問題比兩列? – IamStalker 2012-02-16 05:39:13

+0

MyDBClass是一個包含所有列信息作爲屬性的類。我可以把它當作列表,但是我隨後將它們手動添加到字典中。我只想泛化這個 – Simon 2012-02-16 05:43:33

回答

4

希望這會有所幫助。

 public static class Extensions 
     { 
      public static Dictionary<TKey, TRow> TableToDictionary<TKey,TRow>(
       this DataTable table, 
       Func<DataRow, TKey> getKey, 
       Func<DataRow, TRow> getRow) 
      { 
       return table 
        .Rows 
        .OfType<DataRow>() 
        .ToDictionary(getKey, getRow); 
      } 
     } 



     public static void SampleUsage() 
     { 
      DataTable t = new DataTable(); 

      var dictionary = t.TableToDictionary(
       row => row.Field<int>("ID"), 
       row => new { 
        Age = row.Field<int>("Age"), 
        Name = row.Field<string>("Name"), 
        Address = row.Field<string>("Address"), 
       }); 
     } 

順便說說,您需要包含程序集System.Data.DataSetExtensions.dll才能使用字段擴展方法。

如果您有任何其他問題,請不要猶豫,問。

+0

+1非常感謝!不完全是我之後,但它幫助我找到解決方案。 – Simon 2012-02-16 06:36:21

+0

很高興我能幫你找到解決方案。我知道你基本上有一個2合1的問題,所以我首先回答第一個問題。我假設你更進一步,通過使用目標類型和從表查詢模式之間的反射映射來替換使用方法使其更具動態性? – base2 2012-02-16 06:59:26

+0

正確。如果有人需要下面的答案。非常感謝您指引我朝着正確的方向發展。 – Simon 2012-02-16 07:05:02

1

檢出Petapoco它允許您從數據庫檢索到CLR對象和列表。它沒有太多的開銷。

+0

+1是的這看起來正是我所需要的,但是爲了感興趣,我想知道如何實現這一點>我可能會採用這個爲未來的項目 – Simon 2012-02-16 05:47:16

0

這可以實現通過反射看看這個link可以幫助你 在這篇文章中我曾試圖將數據集轉換成列表

2

與BASE2有很大的幫助,這裏是我的完成方法:

public static IDictionary<TKey, T> ToDictionary<TKey, T>(this DataTable table, Func<DataRow,TKey> getKey) where T : new() 
{ 
    IList<PropertyInfo> properties = GetPropertiesForType<T>(); 
    IDictionary<TKey, T> result = new Dictionary<TKey, T>(); 
    Dictionary<string, int> propDict = GetPropertyDictionary(properties, table); 
    foreach (var row in table.Rows) 
    { 
     var item = CreateItemFromRow<T>((DataRow)row, properties, propDict); 
     TKey pk = getKey((DataRow)row); 
     result.Add(pk,item); 
    } 
    return result; 
} 

可稱爲像這樣:

IDictionary<Int16,DBClient> Clients = sql.GetDataTable("SELECT * FROM Clients").ToDictionary<Int16,DBClient>(r => r.Field<Int16>("PrimaryKeyField")); 
+0

如果有人需要被調用的私有方法(GetPropertiesForType(),GetPropertyDictionary()和CreateItemFromRow()),請在評論中提問。 – Simon 2012-02-16 07:08:22

+0

如果您覺得自己很冒險,可以爲您生成表達式樹,然後爲CreateItemFromRow編譯一個Func 委託。這樣,你只需要針對每種目標類型使用一次反射。 – base2 2012-02-16 07:08:51

+0

有趣,但我真的不知道表達式樹。我猜propDict(用作反射屬性的映射查找)不這樣做嗎?我想生病會讀更多:) – Simon 2012-02-16 07:11:33