需求:
需要将两个字段有部分相同其他不同,且行数都不相同的datatable根据keycolumn合并为一个table。
相当于做了一个left Join。
方法一:
自己写的最原始的方法
优点:在表合并方面能完美达到效果。
缺点:表很大时(几万行开始)速度相当慢,且容易内存溢出。
1 public static DataTable MergeTable(DataTable dtReturn, DataTable dtMerge, string keyName) 2 { 3 foreach (DataColumn dcm in dtMerge.Columns) 4 if (!dtReturn.Columns.Contains(dcm.ColumnName)) 5 dtReturn.Columns.Add(dcm.ColumnName, dcm.DataType); 6 dtReturn.AcceptChanges(); 7 8 foreach (DataRow dr in dtReturn.Rows) 9 foreach (DataRow drm in dtMerge.Rows) 10 if (dr[keyName].ToString().ToLower().Equals(drm[keyName].ToString().ToLower())) 11 { 12 foreach (DataColumn dc in dtReturn.Columns) 13 foreach (DataColumn dcm in dtMerge.Columns) 14 if (dc.ColumnName.Equals(dcm.ColumnName)) 15 if (string.IsNullOrEmpty(dr[dc].ToString())) 16 { 17 dr[dc] = drm[dcm]; 18 break; 19 } 20 break; 21 } 22 23 return dtReturn; 24 }
方法二:
优点:代码上用datatable.merge()原生态。
缺点:方法一,表很大时(几万行开始)速度相当慢,且容易内存溢出。
具体代码不贴了,感觉merge的内部机制也是循环插入。
方法三:
优点:速度超快。
缺点:用标示法删除重复的列,担心误删。(标示得体的情况下误删可能性极小,可忽略)
1 public static DataTable MergeTable(DataTable dtReturn, DataTable dtMerge, string keyName) 2 { 3 var result = (from b in dtReturn.AsEnumerable() 4 join a in dtMerge.AsEnumerable() 5 on b.Field<string>(keyName) equals a.Field<string>(keyName) 6 into temp 7 from t in temp.DefaultIfEmpty() 8 select new { b, t }).ToList(); 9 10 DataTable dtNew = new DataTable(); 11 foreach (DataColumn dc in dtReturn.Columns) 12 dtNew.Columns.Add(dc.ColumnName, dc.DataType); 13 foreach (DataColumn dcm in dtMerge.Columns) 14 if (!dtNew.Columns.Contains(dcm.ColumnName)) 15 dtNew.Columns.Add(dcm.ColumnName, dcm.DataType); 16 else 17 dtNew.Columns.Add(dcm.ColumnName + "1!@#$%", dcm.DataType); 18 19 for (int i = 0; i < result.Count; i++) 20 { 21 DataRow drNew = dtNew.NewRow(); 22 object[] ob = result[i].b.ItemArray; 23 object[] ot = result[i].t.ItemArray; 24 object[] oc = new object[ob.Length + ot.Length]; 25 ob.CopyTo(oc, 0); 26 ot.CopyTo(oc, ob.Length); 27 drNew.ItemArray = oc; 28 dtNew.Rows.Add(drNew); 29 } 30 dtNew.AcceptChanges(); 31 for (int i = dtNew.Columns.Count - 1; i >= 0; --i) 32 if (dtNew.Columns[i].ColumnName.Contains("1!@#$%")) 33 dtNew.Columns.RemoveAt(i); 34 dtNew.AcceptChanges(); 35 dtReturn = dtNew.Copy(); 36 37 return dtReturn; 38 }
至此,完美优化!撒花~~