LINQ: seleziona un object e modifica alcune proprietà senza creare un nuovo object

Usando LINQ, se volevo eseguire qualche query e restituire l’object dalla query, ma modificare solo alcune proprietà in quell’object, come dovrei farlo senza creare un nuovo object e impostare manualmente ogni proprietà? È ansible?

Esempio:

var list = from something in someList select x // but change one property 

Non sono sicuro di quale sia la syntax della query. Ma ecco l’esempio di espressione LINQ espanso.

 var query = someList.Select(x => { x.SomeProp = "foo"; return x; }) 

Quello che fa è usare un metodo anonimo vs ed espressione. Questo ti permette di usare più istruzioni in un lambda. Quindi puoi combinare le due operazioni di impostazione della proprietà e restituire l’object in questo metodo un po ‘succinto.

Se vuoi semplicemente aggiornare la proprietà su tutti gli elementi, allora

 someList.All(x => { x.SomeProp = "foo"; return true; }) 

Preferisco questo. Può essere combinato con altri comandi di linq.

 from item in list let xyz = item.PropertyToChange = calcValue() select item 

Non ci dovrebbe essere alcuna magia LINQ che ti impedisca di farlo. Non utilizzare la proiezione sebbene restituisca un tipo anonimo.

 User u = UserCollection.FirstOrDefault(u => u.Id == 1); u.FirstName = "Bob" 

Ciò modificherà l’object reale, così come:

 foreach (User u in UserCollection.Where(u => u.Id > 10) { u.Property = SomeValue; } 

Non è ansible con gli operatori di query standard, si tratta di Language Integrated Query, non di Language Integrated Update. Ma potresti hide il tuo aggiornamento nei metodi di estensione.

 public static class UpdateExtension { public static IEnumerable ChangeColorTo( this IEnumerable cars, Color color) { foreach (Car car in cars) { car.Color = color; yield return car; } } } 

Ora puoi usarlo come segue.

 cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red); 
 var item = (from something in someList select x).firstordefault(); 

Otterrebbe l’object e quindi potreste fare item.prop1 = 5; per cambiare la proprietà specifica.

O vuoi ottenere un elenco di elementi dal db e modificarlo come prop1 su ciascun elemento in quell’elenco restituito ad un valore specificato? se è così puoi farlo (lo sto facendo in VB perché lo conosco meglio):

 dim list = from something in someList select x for each item in list item.prop1=5 next 

(la lista conterrà tutti gli articoli restituiti con le tue modifiche)

Dal momento che non ho trovato la risposta qui che considero la soluzione migliore, qui a modo mio:

Usare “Seleziona” per modificare i dati è ansible, ma solo con un trucco. Ad ogni modo, “Seleziona” non è fatto per quello. Esegue appena la modifica quando viene utilizzato con “ToList”, perché Linq non viene eseguito prima che i dati siano necessari. Ad ogni modo, la soluzione migliore è usare “foreach”. Nel seguente codice, puoi vedere:

  class Person { public int Age; } class Program { private static void Main(string[] args) { var persons = new List(new[] {new Person {Age = 20}, new Person {Age = 22}}); PrintPersons(persons); //this doesn't work: persons.Select(p => { p.Age++; return p; }); PrintPersons(persons); //with "ToList" it works persons.Select(p => { p.Age++; return p; }).ToList(); PrintPersons(persons); //This is the best solution persons.ForEach(p => { p.Age++; }); PrintPersons(persons); Console.ReadLine(); } private static void PrintPersons(List persons) { Console.WriteLine("================"); foreach (var person in persons) { Console.WriteLine("Age: {0}", person.Age); ; } } } 

Prima di “foreach”, puoi anche fare una selezione di linq …

Se si desidera aggiornare elementi con una clausola Where , l’uso di .Where (…) troncerà i risultati se si esegue questa operazione:

 mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList(); 

Puoi fare aggiornamenti ad articoli specifici nella lista in questo modo:

 mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList(); 

Restituisci sempre l’articolo anche se non apporti modifiche. In questo modo sarà tenuto nella lista.

Spesso ci imbattiamo in ciò in cui vogliamo includere il valore dell’indice e il primo e l’ultimo indicatore in una lista senza creare un nuovo object. Questo ti consente di conoscere la posizione dell’elemento nel tuo elenco, enumerazione, ecc. Senza dover modificare la class esistente e quindi sapere se sei al primo elemento dell’elenco o l’ultimo.

 foreach (Item item in this.Items .Select((x, i) => { x.ListIndex = i; x.IsFirst = i == 0; x.IsLast = i == this.Items.Count-1; return x; })) 

Puoi semplicemente estendere qualsiasi class usando:

 public abstract class IteratorExtender { public int ListIndex { get; set; } public bool IsFirst { get; set; } public bool IsLast { get; set; } } public class Item : IteratorExtender {} 
 User u = UserCollection.Single(u => u.Id == 1); u.FirstName = "Bob"