2009-07-21 2 views
16

Ho IQueryable<someClass> baseListLinq per aggiornare una raccolta con valori di un'altra raccolta?

e List<someOtherClass> someData

Quello che voglio fare è aggiornare gli attributi in alcuni articoli in baseList.

Per ogni elemento in alcuni Dati, voglio trovare l'elemento corrispondente in elenco di base e aggiornare una proprietà dell'articolo.

someOtherClass.someCode == baseList.myCode

posso fare un certo tipo di unione con LINQ e impostare baseList.someData + = someOtherClass.DataIWantToConcantenate.

Probabilmente potrei farlo per iterazione, ma c'è un modo elegante di Linq che posso fare in un paio di linee di codice?

Grazie per eventuali suggerimenti, ~ ck a San Diego

risposta

19

Per associare gli elementi nelle due liste è possibile utilizzare un LINQ join:

var pairs = from d in someData 
      join b in baseList.AsEnumerable() 
       on d.someCode equals b.myCode 
      select new { b, d }; 

questo vi darà un'enumerazione di ogni elemento in someData accoppiato con la sua controparte in baseList. Da lì, è possibile concatenare in un ciclo:

foreach(var pair in pairs) 
    pair.b.SomeData += pair.d.DataIWantToConcantenate; 

Se davvero si intende set concatenazione piuttosto che +=, dare un'occhiata a LINQ di Unione, Intersezione o Tranne metodi.

+0

Questo ha funzionato alla grande per me. Grazie! – Hcabnettek

+0

Grazie mille !! – PramodChoudhari

12

LINQ è per interrogazione - non per l'aggiornamento. Ciò significa che sarà corretto usare LINQ per trovare l'elemento corrispondente, ma per la modifica si dovrebbe utilizzare l'iterazione.

Certo, potresti voler eseguire una query appropriata per ottenere baseList in un modulo efficiente per la prima volta, ad es. a Dictionary<string, SomeClass> in base alla proprietà che verrà utilizzata per trovare l'elemento corrispondente.

3

È possibile convertire il IQueryable<SomeClass> in un List<SomeClass>, utilizzare il metodo ForEach ad anello su di esso e aggiornare gli elementi, poi riconvertire IQueryable:

List<SomeClass> convertedList = baseList.ToList(); 
convertedList.ForEach(sc => 
{ 
    SomeOtherClass oc = someData.First(obj => obj.SomeCode == sc.MyCode); 
    if (oc != null) 
    { 
     sc.SomeData += oc.DataIWantToConcatenate; 
    } 
}); 

baseList = convertedList.AsQueryable(); // back to IQueryable 

Ma può essere più efficiente durante questo utilizzando non- Costrutti LINQ.

+0

funzionerebbe fare un incrocio tra questo approccio e l'approccio accettata, ad esempio (da d in alcuni dati join b in baseList.AsEnumerable() su d.someCode equivale a b.myCode selezionare new {b, d}). ToList.ForEach (a => { a.b.SomeData + = a.d.DataIWantToConcatenate; }); – stevenrcfox

0

Non è possibile trovare semplicemente oggetti che si trovano in una lista ma non nell'altra, perché sono due tipi diversi. Immagino che tu stia confrontando una proprietà chiamata OtherProperty che è comune alle due diverse classi e che condivide lo stesso tipo. In questo caso, utilizzando nient'altro che Linq interroga:

// update those items that match by creating a new item with an 
// updated property 
var updated = 
    from d in data 
    join b in baseList on d.OtherProperty equals b.OtherProperty 
    select new MyType() 
    { 
     PropertyToUpdate = d.PropertyToUpdate, 
     OtherProperty = d.OtherProperty 
    }; 

// and now add to that all the items in baseList that weren't found in data 
var result = 
    (from b in baseList 
    where !updated.Select(x => x.OtherProperty).Contains(b.OtherProperty) 
    select b).Concat(updated); 
2

Come accennato prima, dovrebbe essere una combinazione di ciclo e LINQ

foreach (var someDataItem in someData) 
{ 
    someDataItem.PropertyToUpdate = (baseList.FirstOrDefault(baseListItem => baseListItem .key == someDataItem.key) ?? new SomeClass(){OtherProperty = "OptionalDefaultValue"}).OtherProperty; 
}