Converti il ​​risultato della query Linq in dizionario


346

Voglio aggiungere alcune righe a un database usando Linq to SQL, ma voglio fare un "controllo personalizzato" prima di aggiungere le righe per sapere se devo aggiungere, sostituire o ignorare le righe in entrata. Vorrei mantenere il traffico tra il client e il server DB il più basso possibile e ridurre al minimo il numero di query.

Per fare ciò, voglio recuperare tutte le informazioni necessarie per la convalida e solo una volta all'inizio del processo.

Stavo pensando di fare qualcosa del genere, ma ovviamente non funziona. Qualcuno ha un'idea?

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

Quello che vorrei avere alla fine sarebbe un dizionario, senza dover scaricare tutti gli oggetti ObjectType da TableObject.

Ho anche considerato il seguente codice, ma stavo cercando di trovare un modo corretto:

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

Risposte:


632

Prova a utilizzare il ToDictionarymetodo in questo modo:

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

2
@pawan, è un segnaposto per ogni elemento nell'enumerazione e assume il tipo di oggetti nell'enumerazione.
tvanfosson,

1
@pawan - non sembra giusto. Mi aspetto che var servers = list.Select( s => new { s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" } ).ToDictionary( s => s.ProjectName, s.Url ); questo crei un dizionario digitato dal nome del progetto delle coppie nome / url del progetto.
tvanfosson,

3
Perché l' .Select( t => new { t.Key, t.TimeStamp } )espressione è necessaria?
Ben Collins,

9
@BenCollins: Penso che l'intermedio .Selectinduca l'SQL generato a selezionare solo Key e TimeStamp, anziché selezionare ogni colonna.
Joey Adams,

1
Puoi omettere questo intermediario Selectse stai eseguendo Linq to Object (anziché Linq to SQL)
Pac0,

119

Guardando il tuo esempio, penso che questo sia quello che vuoi:

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

Wow ... Potrebbe essere così semplice ... Dal momento che sono abbastanza nuovo nella programmazione, proverò e farò un po 'di profilazione per assicurarmi che sotto il cofano, non ottengo il colpo dell'intero oggetto. Vi terrò aggiornati.
Tipx,

1
Ho appena fatto il mio controllo. Purtroppo, mentre ottiene TableObj, recupera tutti gli oggetti dal db, quindi finisco per ottenere il trafic hit. Ho anche controllato le query che nel secondo modo in cui ho pubblicato (e volevo evitare) e hanno ottenuto solo gli elementi necessari. Sicuramente fa 2 query, quindi il server stesso deve cercare due volte le tabelle, ma la mappatura degli oggetti è abbastanza semplice.
Tipx,

7
Potresti essere in grado di fare: TableObj.Select (t => new {t.Key, t.TimeStamp}). ToDictionary (t => t.Key, t => t.TimeStamp); LinqToSql dovrebbe essere in grado di notare che si desidera solo due cose (dalla selezione) e restituirle. Non sono sicuro che sia abbastanza intelligente da approfondire le specifiche di ToDictionary ().
Talljoe,

1
SIMPATICO! Ecco la query risultante: SELECT [t0]. [Key], [t0]. [TimeStamp] FROM [TableObj] AS [t0]. Non voglio prendermi il merito per questo, quindi vai avanti e pubblicalo come una risposta! :-P
Tipx,

8

Prova quanto segue

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

O la versione inferita del tipo completo

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

Grazie per la risposta JaredPar. Ho insegnato qualcosa del genere, ma penso che questo restituirebbe tutti gli oggetti di tipo ObjType e Iwant per evitare di dover scaricare gli oggetti interi.
Tipx,

@Tipx, puoi fornire alcune informazioni su cosa vuoi filtrare? L'aggiunta di una clausola di filtro è possibile, ma dalla tua domanda non so cosa sia importante
JaredPar,

Tutto quello che devo sapere se la "nuova riga" deve essere aggiunta, ignorata o sostituita con un'altra riga è il timestamp dell'oggetto. Gli oggetti nel DB hanno molti campi di cui non ho bisogno per la convalida e non voglio ottenere il colpo di prestazione di ottenere gli oggetti interi. Per semplificare, ho una tabella nel mio BD con 20 colonne, 100000 righe e vorrei estrarre un dizionario usando i valori delle prime 2 colonne.
Tipx,

Ho appena controllato le query del server generate da quel codice e come probabilmente sapevi, ottiene tutti gli oggetti.
Tipx,

0

Usa lo spazio dei nomi

using System.Collections.Specialized;

Crea istanza di DataContextClass

LinqToSqlDataContext dc = new LinqToSqlDataContext();

Uso

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

Per recuperare i valori utilizzare 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();

Per chiavi multilinea ?
Kiquenet,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.