DataRelations (従来のヘッダー/詳細ペア) と一緒にリンクされているいくつかの DataTables を持つ DataSet があります。関連テーブルのすべての列を含む単一の DataTable にロット全体を非正規化する簡単な方法はありますか?
テーブル名と列はコンパイル時には不明であり、3 つ以上のテーブル/リレーションが存在する可能性があります。
DataRelations (従来のヘッダー/詳細ペア) と一緒にリンクされているいくつかの DataTables を持つ DataSet があります。関連テーブルのすべての列を含む単一の DataTable にロット全体を非正規化する簡単な方法はありますか?
テーブル名と列はコンパイル時には不明であり、3 つ以上のテーブル/リレーションが存在する可能性があります。
私自身も同じ問題を抱えていましたが、この質問には答えがなかったので、自分でデノーマライザーを書かなければなりませんでした。それほど難しいことではなかったことが判明したので、これはあなた (またはこの問題に遭遇した他の誰か) が使用/拡張できるかもしれない最初のカットです:
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]);
}
}
}
データセットがこれをネイティブにサポートしているとは思いませんが、コードで行うのは簡単です。
最初に空のデータ テーブルを作成し、結合する両方のテーブルから必要なすべての列を追加する必要があります。
次に、メイン テーブルのデータをステップ実行し、関連テーブルのすべての関連行をステップ実行します。関連テーブルの各行に対して、新しいテーブルに新しい行を作成し、両方のデータ行のデータを新しい行に挿入します。
ここではビジュアル スタジオにアクセスできませんが、おわかりいただけたでしょうか。