2009-02-10 15 views
7

Estoy tratando de hacer lo que creo que es algo simple, pero sospecho que simplemente soy demasiado consciente para saber que probablemente estoy haciendo algo mal. Tengo una consulta LINQ retorno:Intentando cambiar las propiedades de una colección IQueryable

IQueryable<CWords> Result 

Dónde CWords es una clase que define como sigue:

public class CWords 
{ 
    public CWords(){} 
    public string _column1{ get; set; } 
    public float _column2{ get; set; } 

    public void fixData(){} 
} 

en mi código, yo estoy tratando de modidy el campo _column2 para cada miembro del Resultado. Intenté:

foreach (CWords item in Result) 
{ 
    item.fixData(); 
} 

Pero, por supuesto, eso no funcionó. el artículo no está en el alcance apropiado, por lo que los cambios que estaba realizando en fixData no incluían el resultado.

Bcause no se puede indexar en IQueryable, mi solución para este iba a hacer lo siguiente:

var items = goodWords.ToList(); 

for (int i = 0; i < items.Count(); i++) 
    { 
    items[i].fixData(); 
    } 

¿Eso es la manera correcta de hacer esto?

Respuesta

13

Brandon, este es un error normal al usar LINQ. Mira, el IQueryable devuelto por LINQ en realidad no contiene tus artículos, es por eso que no puedes indexarlo. Solo tiene suficiente información para realizar la consulta cuando realmente solicita los artículos. Esto se llama "deferred execution", porque la consulta no se ejecuta cuando select, pero más tarde, al enumerar los resultados. Puede buscar "ejecución diferida de linq" y encontrar muchas personas que intentan explicar cómo funciona.

Cuando realiza su foreach, la consulta se ejecuta y está llamando a fixData() en cada elemento, tal como lo desea. Sin embargo, cuando vuelva a acceder a IQueryable, ejecutará la consulta por segunda vez y (dependiendo del proveedor de LINQ que esté utilizando) podrá traer los elementos originales no modificados por segunda vez.

Al llamar a ToList() en IQueryable, está creando una lista en memoria con todos los resultados de la consulta. Ahora puede indexar en esta lista y acceder a ella todo lo que desee sin ejecutar la consulta de nuevo. Si está de acuerdo con tener todos los elementos en la memoria (conjunto de resultados pequeños), usar ToList() puede ser una buena solución para usted.

@PaulG, tiene razón en que puede usar foreach en lugar de for, pero debe guardar una referencia a la lista o bien está justo donde comenzó (con un IQueryable).

var items = goodWords.ToList(); 

foreach (var item in items) 
{ 
    item.fixData(); 
} 
0

Creo que su goodWords es IQueryable<CWords> type?

¿Por qué no me gusta?

foreach (CWords item in goodWords.ToList()) 
{ 
    item.fixData(); 
} 
Cuestiones relacionadas