2012-02-13 107 views
0

我有以下datatable如何[將數據分組]並將結果放入另一個數據表中?

id name name_in 

3 sys  sys 

5 con  con_r 

5 con  con_s 

5 con  con_g 

我想下面就從數據表:

3 sys 

5 con 

如何做到這一點?

我做了以下

var groups = Process_dt.AsEnumerable() 
    .GroupBy(r => r.Field<Int16>("id")); 

但如何把結果在另一個datatable

+0

hmmmmm,這三個答案與我合作,哪一個是最好的:)從性能角度來看 – 2012-02-13 10:38:33

+0

? – 2012-02-13 10:39:06

回答

1

的GroupBy將返回一個IGrouping集合,你可以迭代方式如下:

var dataTable = new DataTable(); 
dataTable.Columns.Add("id", typeof(Int16)); 
dataTable.Columns.Add("name_in", typeof(string)); 
foreach (var group in groups) 
{ 
    dataTable.Rows.Add(group.Key, (group.First())["name_in"]); 
} 
+0

'不能用[]對'System.Linq.IGrouping '表達式應用索引'' – 2012-02-13 10:23:16

+1

@just_name代碼已更新(add First()) – 2012-02-13 10:30:59

+0

hmmmmm,這三個答案適用於我,哪一個是最好的:) – 2012-02-13 10:39:38

2

您是否嘗試過LINQ的獨特()函數?代碼示例:

var groups = (
    from DataRow row in Process_dt.AsEnumerable() 
    select new { 
     id = row.Field<Int16>("id"), 
     name = row.Field<string>("name") 
     } 
    ).Distinct(); 
+0

hmmmmm,這三個答案和我一起工作,哪一個最好:) – 2012-02-13 10:39:55

+1

啊好吧......如果你接受我的,會喜歡的,但是高票比沒有好! :)很高興你排序你的問題,雖然...順便說一句 - 我認爲使用Distinct()可能會比手動循環更有效率。不知何故,我相信微軟優化了LINQ框架以提高速度和內存使用率。請注意,我不知道它是一個數據表。有沒有什麼理由呢?你不能只綁定到任何IEnumerable實現? – FarligOpptreden 2012-02-13 11:41:53

+0

非常感謝:)當所有的答案解決我的問題時,我選擇第一個:)。關於數據表,我選擇轉換爲數據表,因爲我綁定在列表視圖上!這是可能綁定與'var' – 2012-02-13 12:03:37

1

你可以建立自己的CopyToDataTable這需要任何的IEnumerable(不僅DataRow),並返回一個新DataTable

var q=from row in Process_dt.AsEnumerable() 
     group row by (int)row["id"] into IdGroup 
     select new{id=IdGroup.Key,name=IdGroup.First()["name"]}; 
// following does not compile by default 
// because input is not an IEnumerable<DataRow> but an anonymous type, you need code below 
var tblResult = q.CopyToDataTable(); 

這裏是一個實現(與MSDN幫助) :

public class ObjectShredder<T> { 
    private System.Reflection.FieldInfo[] _fi; 
    private System.Reflection.PropertyInfo[] _pi; 
    private System.Collections.Generic.Dictionary<string, int> _ordinalMap; 
    private System.Type _type; 

    // ObjectShredder constructor. 
    public ObjectShredder() { 
     _type = typeof(T); 
     _fi = _type.GetFields(); 
     _pi = _type.GetProperties(); 
     _ordinalMap = new Dictionary<string, int>(); 
    } 

    /// <summary> 
    /// Loads a DataTable from a sequence of objects. 
    /// </summary> 
    /// <param name="source">The sequence of objects to load into the DataTable.</param> 
    /// <param name="table">The input table. The schema of the table must match that 
    /// the type T. If the table is null, a new table is created with a schema 
    /// created from the public properties and fields of the type T.</param> 
    /// <param name="options">Specifies how values from the source sequence will be applied to 
    /// existing rows in the table.</param> 
    /// <returns>A DataTable created from the source sequence.</returns> 
    public DataTable Shred(IEnumerable<T> source, DataTable table, LoadOption? options) { 
     // Load the table from the scalar sequence if T is a primitive type. 
     if (typeof(T).IsPrimitive) { 
      return ShredPrimitive(source, table, options); 
     } 

     // Create a new table if the input table is null. 
     if (table == null) { 
      table = new DataTable(typeof(T).Name); 
     } 

     // Initialize the ordinal map and extend the table schema based on type T. 
     table = ExtendTable(table, typeof(T)); 

     // Enumerate the source sequence and load the object values into rows. 
     table.BeginLoadData(); 
     using (IEnumerator<T> e = source.GetEnumerator()) { 
      while (e.MoveNext()) { 
       if (options != null) { 
        table.LoadDataRow(ShredObject(table, e.Current), (LoadOption)options); 
       } else { 
        table.LoadDataRow(ShredObject(table, e.Current), true); 
       } 
      } 
     } 
     table.EndLoadData(); 

     // Return the table. 
     return table; 
    } 

    public DataTable ShredPrimitive(IEnumerable<T> source, DataTable table, LoadOption? options) { 
     // Create a new table if the input table is null. 
     if (table == null) { 
      table = new DataTable(typeof(T).Name); 
     } 

     if (!table.Columns.Contains("Value")) { 
      table.Columns.Add("Value", typeof(T)); 
     } 

     // Enumerate the source sequence and load the scalar values into rows. 
     table.BeginLoadData(); 
     using (IEnumerator<T> e = source.GetEnumerator()) { 
      Object[] values = new object[table.Columns.Count]; 
      while (e.MoveNext()) { 
       values[table.Columns["Value"].Ordinal] = e.Current; 

       if (options != null) { 
        table.LoadDataRow(values, (LoadOption)options); 
       } else { 
        table.LoadDataRow(values, true); 
       } 
      } 
     } 
     table.EndLoadData(); 

     // Return the table. 
     return table; 
    } 

    public object[] ShredObject(DataTable table, T instance) { 

     FieldInfo[] fi = _fi; 
     PropertyInfo[] pi = _pi; 

     if (instance.GetType() != typeof(T)) { 
      // If the instance is derived from T, extend the table schema 
      // and get the properties and fields. 
      ExtendTable(table, instance.GetType()); 
      fi = instance.GetType().GetFields(); 
      pi = instance.GetType().GetProperties(); 
     } 

     // Add the property and field values of the instance to an array. 
     Object[] values = new object[table.Columns.Count]; 
     foreach (FieldInfo f in fi) { 
      values[_ordinalMap[f.Name]] = f.GetValue(instance); 
     } 

     foreach (PropertyInfo p in pi) { 
      values[_ordinalMap[p.Name]] = p.GetValue(instance, null); 
     } 

     // Return the property and field values of the instance. 
     return values; 
    } 

    public DataTable ExtendTable(DataTable table, Type type) { 
     // Extend the table schema if the input table was null or if the value 
     // in the sequence is derived from type T.    
     foreach (FieldInfo f in type.GetFields()) { 
      if (!_ordinalMap.ContainsKey(f.Name)) { 
       // Add the field as a column in the table if it doesn't exist 
       // already. 
       DataColumn dc = table.Columns.Contains(f.Name) ? table.Columns[f.Name] 
        : table.Columns.Add(f.Name, f.FieldType); 

       // Add the field to the ordinal map. 
       _ordinalMap.Add(f.Name, dc.Ordinal); 
      } 
     } 
     foreach (PropertyInfo p in type.GetProperties()) { 
      if (!_ordinalMap.ContainsKey(p.Name)) { 
       // Add the property as a column in the table if it doesn't exist 
       // already. 
       DataColumn dc = table.Columns.Contains(p.Name) ? table.Columns[p.Name] 
        : table.Columns.Add(p.Name, p.PropertyType); 

       // Add the property to the ordinal map. 
       _ordinalMap.Add(p.Name, dc.Ordinal); 
      } 
     } 

     // Return the table. 
     return table; 
    } 
} 

現在你可以添加這些擴展:

public static class CustomLINQtoDataSetMethods { 
    public static DataTable CopyToDataTable<T>(this IEnumerable<T> source) { 
     return new ObjectShredder<T>().Shred(source, null, null); 
    } 

    public static DataTable CopyToDataTable<T>(this IEnumerable<T> source, 
               DataTable table, LoadOption? options) { 
     return new ObjectShredder<T>().Shred(source, table, options); 
    } 

} 

Voilà!現在CopyToDataTable與任何LINQ查詢:)

+0

hmmmmm,這三個答案和我一起工作,哪一個是最好的:) – 2012-02-13 10:40:02

+1

@just_name:Farligs答案不創建一個DataTable。 VC74的方法比較簡單並且可行,所以可以接受。我的唯一的好處是,你再也不需要從LINQ查詢手動創建一個新的DataTable,因爲'CopyToDataTable'自動執行它。 – 2012-02-13 10:48:14

+0

非常感謝..... – 2012-02-13 10:51:22

相關問題