Linqクエリ結果を辞書に変換


346

Linq to SQLを使用してデータベースにいくつかの行を追加したいが、行を追加する前に「カスタムチェック」を実行して、受信行を追加、置換、または無視する必要があるかどうかを確認したい。クライアントとDBサーバー間のトラフィックをできる限り少なくし、クエリの数を最小限にしたいと考えています。

これを行うには、検証に必要な最小限の情報を、プロセスの最初に一度だけフェッチします。

私はこのようなことをしようと考えていましたが、明らかに、それはうまくいきません。誰かがアイデアを持っていますか?

Dictionary<int, DateTime> existingItems = 
    (from ObjType ot in TableObj
        select (new KeyValuePair<int, DateTime>(ot.Key, ot.TimeStamp))
    )

最後に、TableObjectからObjectTypeオブジェクト全体をダウンロードする必要のないディクショナリが必要です。

次のコードも検討しましたが、適切な方法を見つけようとしました。

List<int> keys = (from ObjType ot in TableObj orderby ot.Key select ot.Key).ToList<int>();
List<DateTime> values = (from ObjType ot in TableObj orderby ot.Key select ot.Value).ToList<int>();
Dictionary<int, DateTime> existingItems = new Dictionary<int, DateTime>(keys.Count);
for (int i = 0; i < keys.Count; i++)
{
    existingItems.Add(keys[i], values[i]);
}

回答:


632

使用してみてください方法のようにように:ToDictionary

var dict = TableObj.ToDictionary( t => t.Key, t => t.TimeStamp );

2
@pawan、それは列挙型の各要素のプレースホルダーであり、列挙型のオブジェクトのタイプを引き受けます。
tvanfosson

1
@pawan-それは正しくないようです。私は期待したいvar servers = list.Select( s => new { s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" } ).ToDictionary( s => s.ProjectName, s.Url ); 。これは、プロジェクト名/ URLのペアのプロジェクト名をキー辞書を作成します。
tvanfosson、2011

3
なぜ.Select( t => new { t.Key, t.TimeStamp } )表現が必要なのですか?
ベンコリンズ

9
@BenCollins:中間体.Selectが原因で、生成されたSQLはすべての列を選択するのではなく、KeyとTimeStampのみを選択すると思います。
ジョーイアダムス

1
SelectLinq to SQLではなくLinq to Objectを実行している場合は、この仲介者を省略できます
Pac0

119

あなたの例を見て、これはあなたが望むものだと思います:

var dict = TableObj.ToDictionary(t => t.Key, t=> t.TimeStamp);

うわー...それは単純かもしれません...私はプログラミングにかなり慣れていないので、それを試して、内部でオブジェクト全体のヒットが得られないことを確認するために少しプロファイリングします。投稿しておきます。
Tipx

1
私はちょうど私のチェックをしました。悲しいことに、TableObjを取得している間に、データベースからすべてのオブジェクトをフェッチしているので、最終的にはトラフィックヒットが発生します。また、2つ目の方法で投稿した(そして回避したかった)クエリをチェックしたところ、必要なアイテムしか取得できませんでした。確かに2つのクエリを実行するため、サーバー自体がテーブルを2回検索する必要がありますが、オブジェクトのマッピングは十分に簡単です。
Tipx

7
あなたができるかもしれません:TableObj.Select(t => new {t.Key、t.TimeStamp})。ToDictionary(t => t.Key、t => t.TimeStamp); LinqToSqlは、(selectからの)2つだけが必要であることを認識し、それらを返す必要があります。ToDictionary()の詳細を掘り下げるのに十分賢いかどうかはわかりません。
Talljoe 2009年

1
いいね!結果のクエリは次のとおりです。SELECT[t0]。[Key]、[t0]。[TimeStamp] FROM [TableObj] AS [t0]。私はこれを信用したくないので、それをanwserとして投稿してください!:-P
2009年

8

以下をお試しください

Dictionary<int, DateTime> existingItems = 
    (from ObjType ot in TableObj).ToDictionary(x => x.Key);

または本格的な型推論版

var existingItems = TableObj.ToDictionary(x => x.Key);

アンサーのJaredParをありがとう。私はそのようなことを教えましたが、これはObjTypeタイプのオブジェクト全体を返すと思います。オブジェクト全体をダウンロードする必要がないようにしたいのですが。
Tipx

@Tipx、何にフィルターをかけたいかに関する情報を提供できますか?フィルター句を追加することは可能ですが、質問からは何が重要か
わかり

「新しい行」を追加するか、無視するか、または別の行を置き換える必要があるかを知る必要があるのは、オブジェクトのタイムスタンプだけです。DB内のオブジェクトには、検証に必要のないフィールドがたくさんあり、オブジェクト全体を取得することによるパフォーマンスへの影響は望んでいません。単純にするために、BDに20列、100 000行のテーブルを取得しました。最初の2列の値を使用して、Dictionaryを抽出します。
Tipx

そのコードによって生成されたサーバークエリを確認したところ、ご存じのとおり、オブジェクト全体が取得されます。
Tipx

0

名前空間を使用

using System.Collections.Specialized;

DataContextクラスのインスタンスを作成する

LinqToSqlDataContext dc = new LinqToSqlDataContext();

使用する

OrderedDictionary dict = dc.TableName.ToDictionary(d => d.key, d => d.value);

値を取得するには、名前空間を使用します

   using System.Collections;

ICollection keyCollections = dict.Keys;
ICOllection valueCollections = dict.Values;

String[] myKeys = new String[dict.Count];
String[] myValues = new String[dict.Count];

keyCollections.CopyTo(myKeys,0);
valueCollections.CopyTo(myValues,0);

for(int i=0; i<dict.Count; i++)
{
Console.WriteLine("Key: " + myKeys[i] + "Value: " + myValues[i]);
}
Console.ReadKey();

Multilpleキー
Kiquenet 2018年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.