2012-02-04 16 views
2

からC#​​のLINQのToDictionaryを使用する:これにより私は、DataTableのに返すSQLクエリ持ったDataTable

SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH 
FROM USER_TAB_COLUMNS 
WHERE TABLE_NAME IN (SELECT DBTABLE FROM MY_APP_SETTINGS) 

を、私は鍵がTABLE_NAMEおよびColumnInfoを持つカスタムクラスであるDictionary<string, List<ColumnInfo>>を、作成したいですプロパティーを使用して、照会で戻される他の3つのフィールドと照合します。だから、これまで私が持っている:

IEnumerable<DataRow> rows = MyDataTable.Rows.Cast<DataRow>(); 
var ExistingColumns = MyDataTable.AsEnumerable().Select(dataRow => rows 
    .Select(row => new { 
     Key = row["TABLE_NAME"], 
     Value = new ColumnInfo(){ 
      ColumnName = row["COLUMN_NAME"].ToString(), 
      DataType = row["DATA_TYPE"].ToString(), 
      DataLength = int.Parse(row["DATA_LENGTH"].ToString()) 
     } 
    }).ToDictionary(data => data.Key, data => data.Value)); 

しかし、これは二つの問題があります。重複キーがあります1)、2)の値は、クラスのちょうど単一のインスタンスではなく、コレクションです。

linqを使用してこの変換を達成するにはどうすればよいですか?

ありがとうございます!

+0

キーが重複している場合は、辞書を使用できません。 – Joe

+0

さて、私はそれらを組み合わせようとしています。ですから、各TABLE_NAMEに対して、そのTABLE_NAMEを持つColumnInfoオブジェクトのリストが必要です。 – Paul

答えて

2

最初に、テーブル名で行をグループ化するには、GroupByを使用します。これにより、テーブル名が一意になります。

IEnumerable<DataRow> rows = MyDataTable.Rows.Cast<DataRow>(); 
Dictionary<string, List<ColumnInfo>> ExistingColumns = rows 
    .GroupBy(r => r["TABLE_NAME"].ToString(), 
      r => new ColumnInfo { 
       ColumnName = r["COLUMN_NAME"].ToString(), 
       DataType = r["DATA_TYPE"].ToString(), 
       DataLength = Int32.Parse(r["DATA_LENGTH"].ToString()) 
      } 
     ) 
    .ToDictionary(g => g.Key, g => g.ToList()); 

group byの最初の引数はキーを選択し、2番目の引数は値を選択します。それで、辞書を作成するのは簡単です。グループgIEnumerable<ColumnInfo>です。したがって、リストは単にg.ToList()で作成することができます。

2

ToDictionary()は1対1である。

1対多は同じ引数を持つToLookup()です。

1

GSergの提案ToLookupは重複キーの問題を解決します。しかし、これを実現してDictionaryを取得する方法を示すために、あなたが最初のグループにテーブル名を必要とし、その後、ToDictionaryを呼び出します。

var query = MyDataTable.AsEnumerable() 
         .GroupBy(row => row["TABLE_NAME"].ToString()) 
         .ToDictionary(g => g.Key, 
    g => g.Select(row => new ColumnInfo() 
    { 
     ColumnName = row["COLUMN_NAME"].ToString(), 
     DataType = row["DATA_TYPE"].ToString(), 
     DataLength = int.Parse(row["DATA_LENGTH"].ToString()) 
    })); 

これはDictionary<string, IEnumerable<ColumnInfo>>を返します。代わりにリストが必要な場合は、SelectステートメントにToList()を追加するだけです。

関連する問題