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

Antworten:

632

Versuchen Sie es mit der folgenden ToDictionaryMethode :

var dict = TableObj.ToDictionary( t => t.Key, t => t.TimeStamp );
tvanfosson
quelle
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);
BKostenlos
quelle
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);
JaredPar
quelle
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();
Salman Mushtaq
quelle
Für Mehrfachschlüssel ?
Kiquenet