Konvertieren Sie das Ergebnis der Linq-Abfrage in ein Wörterbuch


346

Ich möchte einer Datenbank mit Linq to SQL einige Zeilen hinzufügen, aber ich möchte vor dem Hinzufügen der Zeilen eine "benutzerdefinierte Prüfung" durchführen, um festzustellen, ob ich die eingehenden Zeilen hinzufügen, ersetzen oder ignorieren muss. Ich möchte den Verkehr zwischen dem Client und dem DB-Server so gering wie möglich halten und die Anzahl der Abfragen minimieren.

Dazu möchte ich so wenig Informationen abrufen, wie für die Validierung erforderlich sind, und zwar nur einmal zu Beginn des Prozesses.

Ich habe darüber nachgedacht, so etwas zu tun, aber offensichtlich funktioniert es nicht. Hat jemand eine Idee?

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

Am Ende hätte ich gerne ein Wörterbuch, ohne die gesamten ObjectType-Objekte von TableObject herunterladen zu müssen.

Ich habe auch den folgenden Code in Betracht gezogen, aber ich habe versucht, einen richtigen Weg zu finden:

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]);
}

Antworten:


632

Versuchen Sie es mit der folgenden ToDictionaryMethode :

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

2
@pawan, es ist ein Platzhalter für jedes Element in der Aufzählung und nimmt den Typ der Objekte in der Aufzählung an.
Tvanfosson

1
@pawan - das sieht nicht richtig aus. Ich würde erwarten, dass dadurch var servers = list.Select( s => new { s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" } ).ToDictionary( s => s.ProjectName, s.Url ); ein Wörterbuch erstellt wird, das durch den Projektnamen der Projektnamen / URL-Paare verschlüsselt ist.
Tvanfosson

3
Warum ist der .Select( t => new { t.Key, t.TimeStamp } )Ausdruck notwendig?
Ben Collins

9
@ BenCollins: Ich denke, das Intermediate .Selectbewirkt, dass das generierte SQL nur Key und TimeStamp auswählt, anstatt jede Spalte auszuwählen.
Joey Adams

1
Sie können diesen Vermittler weglassen, Selectwenn Sie Linq to Object (anstelle von Linq to SQL)
ausführen

119

Wenn Sie sich Ihr Beispiel ansehen, denke ich, dass Sie Folgendes wollen:

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

Wow ... Es könnte so einfach sein ... Da ich ziemlich neu in der Programmierung bin, werde ich das versuchen und ein wenig profilieren, um sicherzustellen, dass ich unter der Haube nicht den Treffer des gesamten Objekts bekomme. Ich werde Sie auf dem Laufenden halten.
Tipx

1
Ich habe gerade meinen Scheck gemacht. Leider holt es beim Abrufen des TableObj alle Objekte aus der Datenbank, sodass ich am Ende den Verkehrstreffer bekomme. Ich habe auch die Abfragen überprüft, die ich auf die zweite Weise gepostet habe (und vermeiden wollte), und sie erhalten nur die erforderlichen Elemente. Sicher, es werden 2 Abfragen ausgeführt, sodass der Server selbst zweimal die Tabellen durchsuchen muss, aber die Objektzuordnung ist einfach genug.
Tipx

7
Möglicherweise können Sie Folgendes tun: TableObj.Select (t => new {t.Key, t.TimeStamp}). ToDictionary (t => t.Key, t => t.TimeStamp); LinqToSql sollte feststellen können, dass Sie nur zwei Dinge (aus der Auswahl) möchten, und diese zurückgeben. Ich bin mir nicht sicher, ob es klug genug ist, sich mit den Besonderheiten von ToDictionary () auseinanderzusetzen.
Talljoe

1
NETT! Hier ist die resultierende Abfrage: SELECT [t0]. [Key], [t0]. [TimeStamp] FROM [TableObj] AS [t0]. Ich möchte das nicht gutschreiben, also poste es als Antwort! :-P
Tipx

8

Versuche Folgendes

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

Oder die vollwertige, vom Typ abgeleitete Version

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

Danke für die Antwort JaredPar. Ich habe über so etwas unterrichtet, aber ich denke, dies würde die gesamten Objekte vom Typ ObjType zurückgeben, und ich möchte vermeiden, dass die gesamten Objekte heruntergeladen werden müssen.
Tipx

@Tipx, können Sie einige Informationen darüber bereitstellen, wonach Sie filtern möchten? Das Hinzufügen einer Filterklausel ist möglich, aber ich kann Ihrer Frage nicht
entnehmen,

Alles, was ich wissen muss, wenn die "neue Zeile" hinzugefügt, ignoriert oder durch eine andere Zeile ersetzt werden muss, ist der Zeitstempel des Objekts. Die Objekte in der Datenbank enthalten viele Felder, die ich für die Validierung nicht benötige, und ich möchte nicht den Leistungseinbruch erzielen, wenn die gesamten Objekte abgerufen werden. Um es einfach zu halten, habe ich in meiner BD eine Tabelle mit 20 Spalten, 100.000 Zeilen und möchte ein Wörterbuch mit den Werten der ersten beiden Spalten extrahieren.
Tipx

Ich habe gerade die von diesem Code generierten Serverabfragen überprüft und wie Sie wahrscheinlich wussten, werden alle Objekte abgerufen.
Tipx

0

Verwenden Sie den Namespace

using System.Collections.Specialized;

Instanz von DataContextClass erstellen

LinqToSqlDataContext dc = new LinqToSqlDataContext();

Verwenden

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

Verwenden Sie zum Abrufen der Werte den Namespace

   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();

Für Mehrfachschlüssel ?
Kiquenet
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.