2010-10-14 8 views
10

Supongamos que tengo un objeto de negocio como este,Una manera sencilla de actualizar objetos IEnumerable usando LINQ

class Employee 
    { 
     public string name; 
     public int id; 
     public string desgination; 
     public int grade; 
    } 

    List<Employee> lstEmp = new List<Employee>() 
     { 
      new Employee() { name="A",desgination="SE",id=1}, 
      new Employee() { name="b",desgination="TL",id=2}, 
      new Employee() { name="c",desgination="PL",id=3}, 
      new Employee() { name="d",desgination="SE",id=4}, 
      new Employee() { name="e",desgination="SSE",id=5}, 
     }; 

Y si quiero actualizar la calificación de los empleados a 3, cuya designación es "SE", entonces tengo que escribir algo como esto

lstEmp=lstEmp.Select(x => 
      { 
       x.grade = (x.desgination == "SE") ? 3 : x.grade; 
        return x; 
      }).ToList(); 

Pero aquí cuando se utiliza seleccionarlo generará nuevo cada objeto empleado, no actualizar el lstEmp existente, así que tengo que reassgin la lista actualizada a lstEmp.

Me parece que afecta el rendimiento cuando se actualizan grandes actualizaciones con frecuencia. ¿Hay una solución para esto?

+1

Esta pregunta tiene algunas buenas respuestas: http://stackoverflow.com/questions/398871/update-all-objects-in-a-collection-using-linq –

Respuesta

10

Creo que los métodos de LINQ predeterminados admiten actualizaciones en línea. pero usted puede crear sus propios métodos de extensión a achive este

public static void Update<TSource>(this IEnumerable<TSource> outer, Action<TSource> updator) 
     { 
      foreach (var item in outer) 
      { 
       updator(item); 
      } 


     } 

y utilizar de esta manera

lstEmp.Update(x => x.grade = (x.desgination == "SE") ? 3 : x.grade); 
+0

foreach() es una forma sencilla de actualizar artículos. – tster

+3

NO es posible con ForEach() porque es una ley de solo lectura dentro de foreach. – LeMoussel

1

yo diría LINQ se utiliza mainaly para la selección de los datos una vez que los datos, puede utilizar Para cada construcción para actualizar los datos

18

En realidad, su llamada Select existente es modificando los objetos originales en sí mismos - no está creando nuevos objetos de empleado. ¿Qué le hace pensar que es creando nuevas instancias de Employee? Después de todo, no tiene new Employee en ninguna parte dentro de la expresión lambda.

Puede repetir los resultados de la llamada al Select sin llamar al ToList, y aún verá cambios después. Esto significa que su proyección tiene efectos secundarios - eso generalmente es una mala idea. Sin embargo, debe hacer que algo itere sobre los resultados de la proyección. Simplemente llamando al Count() lo haría, por ejemplo. Las consultas LINQ utilizan la ejecución diferida en muchos casos: no aplican la proyección/predicado/etc. hasta que se necesite el resultado.

LINQ está diseñado para funcionar de una manera funcional: se desaconsejan los efectos secundarios, al igual que no esperaría una consulta SELECT normal en una base de datos para cambiar el contenido de la tabla que está consultando. El código libre de efectos laterales es excelente en términos de legibilidad y la capacidad de razonar sobre el código.

Si desea cambiar los valores en lugar de crear nuevos, sugeriría un simple foreach bucle en su lugar. No es para lo que está diseñado LINQ. Sin embargo, yo personalmente trataría de mantener los tipos inmutables, usar LINQ y medir el rendimiento sobre la marcha. Sospecho que descubrirá que en muchos casos no es tan malo como cree.

-2
lstEmp = lstEmp.Select(X => new Employee 
     { 
      desgination =X.desgination , 
      grade =X.desgination=="SE"?3:X.grade , 
      id=X.id , 
      name =X.name 
     }).ToList(); 
Cuestiones relacionadas