2008-10-28 6 views
72

Jak poprawnie przekonwertować dwie kolumny z SQL (2008) używając Linq do słownika (do buforowania)?Linq-to-SQL ToDictionary()

Obecnie przechodzę przez IQueryable b/c Nie mogę uruchomić metody ToDictionary. Jakieś pomysły? to działa:

var query = from p in db.Table 
      select p; 

Dictionary<string, string> dic = new Dictionary<string, string>(); 

foreach (var p in query) 
{ 
    dic.Add(sub.Key, sub.Value); 
} 

Co naprawdę chciałbym zrobić, to coś takiego, co nie wydaje się działać:

var dic = (from p in db.Table 
      select new {p.Key, p.Value }) 
      .ToDictionary<string, string>(p => p.Key); 

Ale otrzymuję ten błąd: nie można przekonwertować z ' System.Linq.IQueryable”do«System.Collections.Generic.IEnumerable»

Odpowiedz

108
var dictionary = db 
    .Table 
    .Select(p => new { p.Key, p.Value }) 
    .AsEnumerable() 
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value) 
; 
+0

Niestety, być może nie było jasne, próbowałem wcześniej, ale to tworzy słownik , a nie słownik Codewerks

+0

Wypróbuj 'kvp => kvp.Value jako ciąg '. Punktem odpowiedzi była '.AsEnumerable()'. – yfeldblum

+0

Dzięki, tak, pomyślałem, że AsEnumerable było potrzebne, ale wywołanie ToDictionary nadal nie działa. Obie kolumny są varcharami w SQL, więc wracają jako ciągi znaków, ale nie mogę wymyślić, jak je wprowadzić do Dic ... – Codewerks

13

definiowania tylko klucz, ale trzeba podać wartość również:

var dic = (from p in db.Table 
      select new {p.Key, p.Value }) 
      .ToDictionary(p => p.Key, p=> p.Value); 
+0

Wypróbowałem to również wcześniej, ale to powoduje błąd konstrukcyjny, "Nazwa" p "nie istnieje w bieżącym" – Codewerks

+0

zorientował się, dzięki za pomoc! – Codewerks

+0

Nie ma za co :-) – CMS

9

Dzięki chłopaki, wasze odpowiedzi pomógł mi rozwiązać ten powinien być:

var dic = db 
     .Table 
     .Select(p => new { p.Key, p.Value }) 
     .AsEnumerable() 
     .ToDictionary(k=> k.Key, v => v.Value); 
+5

Powodem, dla którego potrzebujesz AsEnumerable(), jest to, że LINQ do SQL nie miesza przetwarzania lokalnego i zdalnego (SQL), więc powoduje to wykonanie pierwszej części na serwerze SQL, a następnie końcową kolejną część do wykonaj lokalnie używając LINQ do obiektów, które mogą tworzyć słowników :) – DamienG

+0

To ma sens. Ponadto drugi parametr w ToDictionary wymaga własnych argumentów Func, co wcześniej mnie potknęło. – Codewerks

1

Dlaczego chcesz utworzyć anonimowy obiekt dla każdej pozycji w tabeli po prostu go przekonwertować?

Można po prostu użyć czegoś takiego: IDictionary<string, string> dic = db.Table.ToDictionary(row => row.Key, row => row.Value); Może trzeba będzie obejmować AsEnumerable() połączenia między stołem a ToDictionary(). Nie znam dokładnego typu tabeli db.Table.


poprawić także pierwsza próbka, zmienna druga pętla jest niedopasowanie w deklaracji i użytkowania.

+2

Ponieważ 'ToDictionary' jest w pamięci. Nie tworzenie anonimowego obiektu oznacza, że ​​wszystkie kolumny są pobierane z bazy danych, a nie tylko te, które są potrzebne. – Stijn

+0

'ToDictionary' nie wie o podstawowej strukturze, po prostu wywołuje dwa wywołania zwrotne dla klucza i wartości (w tym przypadku prosta właściwość wybierając lambdas), więc to wywołanie' ToDictionary' powinno być funkcjonalnie równoważne z foreach w przykładzie opatrzony. O ile mi wiadomo, wszystkie metody LINQ są odłożone, co oznacza, że ​​callbacki są wywoływane tylko wtedy, gdy jest to konieczne. – TWiStErRob

+3

Jeśli spojrzysz z programem SQL Server Profiler, zobaczysz, że w przypadku anonimowego obiektu wybierane są tylko dwie kolumny, a bez niego wszystkie kolumny są zaznaczone. – Stijn