2009-02-06 7 views
3

J'ai un DataSet avec des DataTables qui sont liés avec DataRelations (paire d'en-têtes/détails d'ordre classique). Y at-il un moyen facile de dénormaliser le lot entier dans un seul DataTable avec toutes les colonnes des tables liées? Les noms et colonnes des tables ne sont pas connus au moment de la compilation et il peut y avoir plus de deux tables/relations.Dénormaliser un DataSet

Répondre

2

Avait le même problème moi-même, mais puisque cette question n'a pas eu de réponse, j'ai dû écrire le dénormaliseur moi-même. Il s'est avéré que ce n'était pas si difficile - donc c'est une première coupe que vous (ou quelqu'un d'autre qui rencontre ce problème) pourrait utiliser/étendre:

public class DataSetDenormalizer 
{ 
    public void DenormalizeRelationships(DataSet dataSet) 
    { 
     IOrderedEnumerable<DataRelation> orderedRelationship = SortRelationshipsByNumberOfChildRows(dataSet); 
     var tablesToRemove = new List<DataTable>(); 

     foreach (DataRelation relationship in orderedRelationship) 
     { 
      DenormalizeColumns(relationship); 
      DenormalizeData(relationship); 
      RemoveDenormalizedRelationships(dataSet, relationship, tablesToRemove); 
     } 
    } 

    private IOrderedEnumerable<DataRelation> SortRelationshipsByNumberOfChildRows(DataSet dataSet) 
    { 
     var relationships = new List<DataRelation>(); 
     foreach (DataRelation relationship in dataSet.Relations) 
      relationships.Add(relationship); 
     return relationships.OrderBy(r => r.ChildTable.Rows.Count); 
    } 

    private void DenormalizeColumns(DataRelation relationship) 
    { 
     for (int columnIndex = 0; columnIndex < relationship.ParentTable.Columns.Count; ++columnIndex) 
     { 
      DataColumn column = relationship.ParentTable.Columns[columnIndex]; 
      if (relationship.ParentColumns.Contains(column)) continue; 
      relationship.ChildTable.Columns.Add(new DataColumn(column.ColumnName, column.DataType)); 
     } 
    } 

    private void DenormalizeData(DataRelation relationship) 
    { 
     for (int rowIndex = 0; rowIndex < relationship.ChildTable.Rows.Count; ++rowIndex) 
     { 
      DataRow row = relationship.ChildTable.Rows[rowIndex]; 
      DataRow parentRow = row.GetParentRow(relationship); 

      for (int columnIndex = 0; columnIndex < relationship.ParentTable.Columns.Count; ++columnIndex) 
      { 
       DataColumn column = relationship.ParentTable.Columns[columnIndex]; 
       if (relationship.ChildTable.Columns.Contains(column.ColumnName)) 
       { 
        row.SetField(column.ColumnName, parentRow[column]); 
       } 
      } 
     } 
    } 

    private void RemoveDenormalizedRelationships(DataSet dataSet, DataRelation relationship, List<DataTable> tablesToRemove) 
    { 
     dataSet.Relations.Remove(relationship); 
     relationship.ChildTable.Constraints.Remove(relationship.RelationName); 

     if (!tablesToRemove.Contains(relationship.ParentTable)) 
      tablesToRemove.Add(relationship.ParentTable); 

     int numberOfColumns = relationship.ChildColumns.Length; 
     for (int columnIndex = 0; columnIndex < numberOfColumns; ++columnIndex) 
     { 
      relationship.ChildTable.Columns.Remove(relationship.ChildColumns[columnIndex]); 
     } 
    } 
} 
0

Je ne pense pas que les ensembles de données le supportent nativement, mais il est assez facile de faire du code.

Vous devez d'abord créer une table de données vide, puis ajouter toutes les colonnes dont vous avez besoin des deux tables que vous souhaitez combiner.

Ensuite, vous parcourez les données de votre table principale et parcourez toutes les lignes connexes de la table associée. Pour chaque ligne de la table associée, vous créez une nouvelle ligne dans votre nouvelle table et insère les données des deux lignes de données dans la nouvelle.

Je n'ai pas accès au studio visuel ici maintenant, mais vous avez l'idée.