2016-05-09 1 views
2

У меня есть, например, 4 DataTables:Петля через несколько таблиц данных (доля одного столбца)

private void Test() 
{ 
    DataTable table1 = new DataTable(); 
    table1.Columns.Add("MyId"); 
    table1.Columns.Add("Column1"); 
    table1.Columns.Add("Column2"); 

    DataTable table2 = new DataTable(); 
    table2.Columns.Add("Column3"); 
    table2.Columns.Add("MyId"); 
    table2.Columns.Add("Column4"); 

    DataTable table3 = new DataTable(); 
    table3.Columns.Add("Column5"); 
    table3.Columns.Add("MyId"); 
    table3.Columns.Add("Column6"); 

    DataTable table4 = new DataTable(); 
    table4.Columns.Add("Column7"); 
    table4.Columns.Add("Column8"); 
    table4.Columns.Add("MyId"); 

    DataSet set = new DataSet(); 
    set.Tables.Add(table1); 
    set.Tables.Add(table2); 
    set.Tables.Add(table3); 
    set.Tables.Add(table4); 

    set.Relations.Add("MYKEY", table1.Columns["MyId"], table2.Columns["MyId"]); 
    set.Relations.Add("MYKEY", table1.Columns["MyId"], table3.Columns["MyId"]); 
    set.Relations.Add("MYKEY", table1.Columns["MyId"], table4.Columns["MyId"]); 

    foreach (DataTable dt in set.Tables) 
    { 
     foreach (DataRow item in dt.Rows[0].GetChildRows("MYKEY")) 
     { 
      int id = Convert.ToInt32(item["MyId"]); 
      string column1 = item["Column1"].ToString(); 
      string column8 = item["Column8"].ToString(); 
     } 
    } 
} 

Является ли возможно осуществить связь, где все DataTables соединены на основе столбца «MyId»? Я хотел бы пропустить все строки только с одним циклом.

Я уже читал 'Adding DataRelations на сайте MSDN, но не могу определить несколько отношений с тем же именем.

ответ

2

Я думаю, короткий ответ на ваш вопрос «Нет, это не способ перебора всех строк во всех связанных таблицах с помощью всего лишь один цикла использования DataRelation класса или набора из него в».

Класс DataRelation разработан [для моего лучшего понимания], чтобы обеспечить ограничения в коде, которые обычно применяются на уровне базы данных, такие как отношения Первичный ключ -> Внешние ключи. Тем не менее, он не предназначен для простого перемещения данных, т. Е. Для доступа к данным необходимо знание базовой структуры данных (таблиц/столбцов).

Есть способы сбора данных через один цикл, но я не уверен, насколько значимым будет такой сбор данных. Вот пример использования Dictionary<int, List<Tuple<string, object>>>, где ключ является первичным ключом в таблице, и данные сгруппированы в имя столбец/значение пар:

 var data = new Dictionary<int, List<Tuple<string, object>>>(); 

     foreach (DataRow row in table1.Rows) 
     { 
      /* Pull data from "main" table */ 

      int id = Convert.ToInt32(row["MyId"]); 
      var rowData = new List<Tuple<string, object>>(); 

      foreach (DataColumn column in table1.Columns) 
      { 
       string columnName = column.ColumnName; 
       var columnData = new Tuple<string, object>(columnName, row[columnName]); 

       rowData.Add(columnData); 
      } 

      //Collect data from each related table 
      foreach (DataRelation relation in set.Relations) 
      { 
       foreach (DataRow relatedRow in row.GetChildRows(relation)) 
       { 
        foreach (DataColumn column in relation.ChildTable.Columns) 
        { 
         if (relation.ChildColumns.Contains(column)) 
         { 
          continue; 
         } 

         string columnName = column.ColumnName; 
         var columnData = new Tuple<string, object>(columnName, relatedRow[columnName]); 

         rowData.Add(columnData); 
        } 
       } 
      } 

      //Add to data dictionary 
      data.Add(id, rowData); 
     } 

Преимущество приведенного выше кода нет зависимости от структуры таблицы в все (за исключением очевидной необходимости идентифицировать основную таблицу и первичный ключ); но вам все равно нужно написать довольно немного кода для значимого анализа результирующей структуры данных.

Я думаю, что запрос LINQ был бы намного более ясным и выразительным в этом случае. Я знаю, что это не то, о чем вы просили, но на случай, если вам это интересно, вот решение LINQ, которое обеспечивает эквивалент данных SQL, представленный как перечислимый для значимых объектов:

var fullDataView = from t1data in table1.AsEnumerable() 
          join t2data in table2.AsEnumerable() 
          on t1data["MyId"] equals t2data["MyId"] 
          join t3data in table3.AsEnumerable() 
          on t1data["MyId"] equals t3data["MyId"] 
          join t4data in table4.AsEnumerable() 
          on t1data["MyId"] equals t4data["MyId"] 
          select new 
          { 
           MyId = t1data["MyId"], 
           Column1 = t1data["Column1"], 
           Column2 = t1data["Column2"], 
           Column3 = t2data["Column3"], 
           Column4 = t2data["Column4"], 
           Column5 = t3data["Column5"], 
           Column6 = t3data["Column6"], 
           Column7 = t4data["Column7"], 
           Column8 = t4data["Column8"] 
          }; 
Смежные вопросы