2008-10-28 30 views
72

¿Cómo convierto correctamente dos columnas de SQL (2008) utilizando Linq en un diccionario (para el almacenamiento en caché)?Linq-to-SQL ToDictionary()

Actualmente recorro el b/c de IQueryable No puedo obtener el método ToDictionary para que funcione. ¿Algunas ideas? Esto funciona :

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

Lo que realmente me gustaría hacer es algo como esto, lo que no parece funcionar:

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

pero me sale este error: No se puede convertir de ' System.Linq.IQueryable' a 'System.Collections.Generic.IEnumerable'

Respuesta

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

Lo siento, puede que no haya sido claro, lo intenté antes, pero esto crea un Dictionary , no Dictionary Codewerks

+0

Pruebe 'kvp => kvp.Value as string '. El punto de la respuesta fue '.AsEnumerable()'. – yfeldblum

+0

Gracias, sí, pensé que se necesitaba AsEnumerable, pero la llamada ToDictionary aún no funciona. Ambas columnas son varcars en SQL, por lo que vuelven como cadenas, pero no puedo encontrar la manera de hacerlo llegar a un Dic .... – Codewerks

13

está definiendo solamente la llave, pero hay que incluir el valor también:

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

Intenté esto también antes, pero esto arroja un error de compilación, "El nombre 'p' no existe en el actual" – Codewerks

+0

lo resolvió, gracias por su ayuda! – Codewerks

+0

De nada :-) – CMS

9

Gracias chicos, sus respuestas me ayudó a solucionar este problema, deben ser:

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

La razón por la que necesita AsEnumerable() es porque LINQ to SQL no mezcla el procesamiento local y remoto (SQL) por lo que esto hace que la primera parte se ejecute en el servidor SQL y luego la última parte posterior a ejecutar localmente usando LINQ para objetos que pueden hacer Dictionarys :) – DamienG

+0

Tiene sentido. Además, el segundo parámetro en ToDictionary necesita sus propios argumentos de Func, lo que me estaba haciendo tropezar antes. – Codewerks

1

¿Por qué se crea un objeto anónimo para cada elemento de la tabla sólo para convertirlo?

Simplemente podría utilizar algo como: IDictionary<string, string> dic = db.Table.ToDictionary(row => row.Key, row => row.Value); Es posible que tenga que incluir una llamada AsEnumerable() entre la tabla y ToDictionary(). No sé el tipo exacto de db.Table.


Corrija también la primera muestra, la segunda variable de bucle no coincide en la declaración y el uso.

+2

Porque 'ToDictionary' está en la memoria. No crear un objeto anónimo significa que todas las columnas se recuperan de la base de datos en lugar de solo las que necesita. – Stijn

+0

'ToDictionary' no conoce la estructura subyacente, solo llama a las dos devoluciones de llamada para clave y valor (en este caso, propiedad simple seleccionando lambdas), por lo que esta llamada' ToDictionary' debería ser funcionalmente equivalente a foreach en el ejemplo que previsto. Hasta donde yo sé, todos los métodos LINQ son diferidos, es decir, solo se llaman cuando es necesario. – TWiStErRob

+3

Si mira con SQL Server Profiler, verá que con un objeto anónimo solo se seleccionan dos columnas, y sin ella se seleccionan todas las columnas. – Stijn

Cuestiones relacionadas