2012-05-08 13 views
5

Tôi đang cố gắng để nối hai DataTables với nhau trong một cách tương tự như câu hỏi này:C# DataTable Nội tham gia với các cột năng động

Inner join of DataTables in C#

Tôi đang cố gắng để có được kết quả là một đơn 'kết hợp 'bảng, với các cột từ cả hai bảng gốc. Cả hai đều có một cột dữ liệu chung.

Câu trả lời được đưa ra là tốt cho DataTables với cột cố định, nhưng nếu chúng được tạo động và có thể có số cột, làm cách nào để tham gia?

ví dụ:

T1 (datestamp, t1Column1, t1Column2, t1ColumnN...) 
T2 (datestamp, t2Column1, t2Column2, t2ColumnN...) 

Tôi muốn tham gia để tạo ra những điều sau đây:

J1 (datestamp, t1Column1, t1Column2, t1ColumnN, ..., t2Column1, t2Column2, t2ColumnN...) 

Đây có phải là có thể?

+0

Bạn có thể sử dụng "LINQ" không? –

+0

Bạn có thể đưa ra ví dụ về một số dữ liệu sẽ là kết quả bạn muốn không? –

+0

Tôi không nghĩ rằng LINQ là một lựa chọn vì bạn sẽ cần phải biết tên cột bạn đang cố gắng để dự án vào. – finoutlook

Trả lời

7

Tôi đã tìm thấy giải pháp không dựa vào việc lặp qua các cột.

Phương thức này sử dụng phương pháp 'Hợp nhất' mà trước đây tôi đã loại bỏ vì tôi nghĩ cả hai bảng đều yêu cầu cùng một cấu trúc.

Trước tiên, bạn cần phải tạo ra một khóa chính trên hai dữ liệu bảng:

// set primary key 
T1.PrimaryKey = new DataColumn[] { T1.Columns["DateStamp"] }; 
T2.PrimaryKey = new DataColumn[] { T2.Columns["DateStamp"] }; 

Sau đó thêm cả hai bảng vào một dữ liệu thiết lập nên một mối quan hệ có thể được thêm vào:

// add both data-tables to data-set 
DataSet dsContainer = new DataSet(); 
dsContainer.Tables.Add(T1); 
dsContainer.Tables.Add(T2); 

Tiếp theo thêm mối quan hệ giữa hai cột chính trong tập dữ liệu:

// add a relationship between the two timestamp columns 
DataRelation relDateStamp = new DataRelation("Date", new DataColumn[] { T1.Columns["DateStamp"] }, new DataColumn[] { T2.Columns["DateStamp"] }); 
dsContainer.Relations.Add(relDateStamp); 

Cuối cùng, bạn có thể sao chép tệp đầu tiên dữ liệu bảng vào một phiên bản 'kết hợp' mới, và sau đó hợp nhất trong lần thứ hai:

// populate combined data 
DataTable dtCombined = new DataTable(); 
dtCombined = T1.Copy(); 
dtCombined.Merge(T2, false, MissingSchemaAction.Add); 

Lưu ý: Phương pháp Merge đòi hỏi đối số thứ hai là sai hoặc nếu không nó sao chép cấu trúc nhưng không phải là dữ liệu thứ hai bàn.

này sau đó sẽ kết hợp các bảng sau:

T1 (2012-05-09, 111, 222) 
T2 (2012-05-09, 333, 444, 555) 

vào một phiên bản kết hợp dựa trên khóa chính:

J1 (2012-05-09, 111, 222, 333, 444, 555) 
1

Tôi nghĩ bạn có thể điều chỉnh câu trả lời trong câu hỏi được liên kết để sử dụng số index of the column, thay vì tên cột. Hoặc bạn chỉ có thể lặp qua các mục trong mỗi Hàng, như sau:

foreach(DataRow row in table.Rows) 
{ 
    foreach(DataColumn column in table.Columns) 
    { 
     object value = row[column]; // add this to your combined table 
    } 
} 
+0

Cảm ơn - Tôi đã hy vọng tránh lặp qua tất cả các cột vì tôi đã có một vài vòng lồng nhau để thiết lập các bảng gốc. Điều này có thể khá phức tạp nếu dữ liệu trong các bảng có nhiều ngày/khóa khác nhau. – finoutlook

1

Sau khi nhận được mệt mỏi của nhìn thấy tất cả tham gia những nội chức năng mà don' t mô phỏng một cách đáng tin cậy SQL, tôi quyết định tự làm cho mình ở đây:

private DataTable JoinDataTables(DataTable t1, DataTable t2, params Func<DataRow, DataRow, bool>[] joinOn) 
{ 
    DataTable result = new DataTable(); 
    foreach (DataColumn col in t1.Columns) 
    { 
     if (result.Columns[col.ColumnName] == null) 
      result.Columns.Add(col.ColumnName, col.DataType); 
    } 
    foreach (DataColumn col in t2.Columns) 
    { 
     if (result.Columns[col.ColumnName] == null) 
      result.Columns.Add(col.ColumnName, col.DataType); 
    } 
    foreach (DataRow row1 in t1.Rows) 
    { 
     var joinRows = t2.AsEnumerable().Where(row2 => 
      { 
       foreach (var parameter in joinOn) 
       { 
        if (!parameter(row1, row2)) return false; 
       } 
       return true; 
      }); 
     foreach (DataRow fromRow in joinRows) 
     { 
      DataRow insertRow = result.NewRow(); 
      foreach (DataColumn col1 in t1.Columns) 
      { 
       insertRow[col1.ColumnName] = row1[col1.ColumnName]; 
      } 
      foreach (DataColumn col2 in t2.Columns) 
      { 
       insertRow[col2.ColumnName] = fromRow[col2.ColumnName]; 
      } 
      result.Rows.Add(insertRow); 
     } 
    } 
    return result; 
} 

Bài kiểm tra ple về cách bạn có thể sử dụng điều này:

var test = JoinDataTables(transactionInfo, transactionItems, 
       (row1, row2) => 
       row1.Field<int>("TransactionID") == row2.Field<int>("TransactionID")); 
+0

Thực hiện tốt. Có cách nào để sửa đổi nó để có thể chỉ định một toán tử AND hoặc OR giữa nhiều điều kiện "join on" không? – Igor