2014-02-12 18 views
0

我在開發中遇到DataTable.Merge存在的一個奇怪問題。我正試圖將兩個表合併爲一個。我使用下面的代碼DataTable.Merge問題:添加新列(由於區分大小寫)

gridData.Merge(existingGridData); 

的GridData有列 「PK」, 「A」, 「B」, 「AA」, 「BB」 和existingGridData包含 「PK」, 「A」, 「B」, 「C」。

合併結果實際上包含以下列「PK」,「A」,「B」,「AA」,「BB」,「A」,「B」,「C」(列被複制)。

任何想法?我也試過

gridData.Merge(existingGridData, false, MissingSchemaAction.Ignore); 

在這種情況下,主鍵不會被複制到合併結果,我得到了約束違例異常。

我的表實際上有擴展屬性(對於列),我也複製擴展屬性後嘗試,以便兩個表具有相同的擴展屬性。我驗證了列名,標題,數據類型和全部相同。

兩張桌子在不同的地方建造,沒有先前的關係。

我在一個新的解決方案中嘗試了各種情況,它工作正常。

任何幫助?提前致謝。

回答

0

根本原因:我發現它爲什麼發生。我已經將gridData的標題更改爲代碼中的某處的小寫字母。詳細地說,我從數據庫中提取數據。那時列名是ALLCAPS,說「SAMPLEFIELD」。然後在下面的代碼中,我將列名稱(不是標題)重命名爲「SampleField」。 existingGridData還包含「SampleField」。我預計這兩個領域將被合併,但不是。

當通過.Net框架代碼進行調試時,我發現第一次添加列時,會出現一個帶有列名的字典(Columns.columnFromName)。但是,當您更改列名稱時,該字典不會更新 - 如果您提供的CAPS更改的列名稱相同(但如果名稱不同,則會更新)。

此字典在合併期間使用。由於案件更改失敗。嘗試下面的代碼。

for (int i = 0; i < existingData.Columns.Count; i++) 
{ 
    DataColumn src = existingData.Columns[i]; 

    DataColumn dest = (gridData.Columns.Contains(src.ColumnName)) ? gridData.Columns[src.ColumnName] : null; 
    if (dest == null) 
    { 
     //You will get the column here 
    } 

    BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic; 
    MethodInfo minfo = typeof(DataColumnCollection).GetMethod("Contains", bindingFlags); //This override is used internally duting Merge 

    var result = minfo.Invoke(gridData.Columns, new object[]{src.ColumnName, true}); 
    dest = ((bool)result) ? gridData.Columns[src.ColumnName] : null;        

    if (dest == null) 
    { 
     //You wont get the column here. Its case sensitive        
    } 
} 

其他一些與區分大小寫相關的問題。 http://forums.asp.net/t/707552.aspx

希望這有助於有人

0

請參見下面的代碼它給正確的輸出

DataTable dataTable = new DataTable(); 
      dataTable.Columns.Add("PK"); 
      dataTable.Columns.Add("A"); 
      dataTable.Columns.Add("B"); 
      dataTable.Columns.Add("AA"); 
      dataTable.Columns.Add("BB"); 

      DataRow drRow = dataTable.NewRow(); 
      drRow[0] = 1; 
      drRow[1] = 2; 
      drRow[2] = 1; 
      drRow[3] = 2; 
      drRow[4] = 1; 
      dataTable.Rows.Add(drRow); 

      drRow = dataTable.NewRow(); 
      drRow[0] = 3; 
      drRow[1] = 4; 
      drRow[2] = 12; 
      drRow[3] = 23; 
      drRow[4] = 14; 
      dataTable.Rows.Add(drRow); 


      DataTable newTable = new DataTable(); 

      newTable.Columns.Add("PK"); 
      newTable.Columns.Add("A"); 
      newTable.Columns.Add("B"); 
      newTable.Columns.Add("C"); 

      newTable.ExtendedProperties.Add("TimeStamp",DateTime.Now); 

      drRow = newTable.NewRow(); 
      drRow[0] = 5; 
      drRow[1] =6; 
      drRow[2] = 5; 
      drRow[3] = 6; 
      newTable.Rows.Add(drRow); 

      drRow = newTable.NewRow(); 
      drRow[0] = 7; 
      drRow[1] = 8; 
      drRow[2] = 55; 
      drRow[3] = 66; 
      newTable.Rows.Add(drRow); 

      dataTable.Merge(newTable,false); 
+0

我發現的實際問題。看到我的答案。 – Vivasaayi

0

你有2種方法,你可以遵循。要麼你自己創建邏輯,就像我在下面的方法中做的那樣,要麼你可以使用內置的LINQ函數,就像我的第二種方法。

 
/// 
     /// This method is used to merge a set of data tables, based on common columns between them both 
     /// 
     /// 
     /// 
     /// 
     public static DataTable MergeDataTables(DataTable dt1, DataTable dt2) 
     { 
      try 
      { 
       // Get common columns 
       var commonColumns = dt1.Columns.OfType().Intersect(dt2.Columns.OfType(), new DataColumnComparer()); 

       // Create the result which is going to be sent to the user 
       DataTable result = new DataTable(); 

       // Add all the columns from both tables 
       result.Columns.AddRange(
        dt1.Columns.OfType() 
        .Union(dt2.Columns.OfType(), new DataColumnComparer()) 
        .Select(c => new DataColumn(c.Caption, c.DataType, c.Expression, c.ColumnMapping)) 
        .ToArray()); 


       // Add the records of each data table to the new data table, based on the columns 
       var rowData = dt1.AsEnumerable().Join(
        dt2.AsEnumerable(), 
        row => commonColumns.Select(col => row[col.Caption]).ToArray(), 
        row => commonColumns.Select(col => row[col.Caption]).ToArray(), 
        (row1, row2) => 
        { 
         var row = result.NewRow(); 
         row.ItemArray = result.Columns.OfType().Select(col => row1.Table.Columns.Contains(col.Caption) ? row1[col.Caption] : row2[col.Caption]).ToArray(); 
         return row; 
        }, 
        new ObjectArrayComparer()); 

       // Loop and add 
       foreach (var row in rowData) 
        result.Rows.Add(row); 

       // Return result... 
       return result; 
      } 
      catch (Exception ex) 
      { 
       throw new Exception("Problem while merging data tables. Check that there are common columns between the 2 data tables. Error : " + ex.Message); 
      } 
     } 

或者執行以下操作;

 
// Results 
       DataTable reportResult1 = new DataTable(); // Your data table 1 
       DataTable reportResult2 = new DataTable(); // Your data table 2 

       // Merge tables 
       var commonColumns = reportResult1.Columns.OfType().Intersect(reportResult2.Columns.OfType(), new DataColumnComparer()); 

       // Remove DB Nulls, replace with empty strings 
       reportResult1.RemoveColumnNulls(commonColumns.ToList()); 
       reportResult2.RemoveColumnNulls(commonColumns.ToList()); 

       reportResult1.PrimaryKey = commonColumns.ToArray(); 
       result.Merge(reportResult2, false, MissingSchemaAction.AddWithKey); 
       result.Merge(reportResult1, false, MissingSchemaAction.AddWithKey); 

       return result; 

讓我知道你是否管理。我會選擇2號選項,因爲它在性能方面更加優化。所做的是提取2個表格之間的公共列,創建另一個表格,並且您將具有FULL OUTER JOIN效果。常用列將用作JOINed列。