none
LinQ - Liste - Property ändern RRS feed

  • Frage


  • Hallo Community,
    var list = ctn.Items
        .Where(t=> t.Used == false)
        .OrderBy(t => t.Position)
        .Take(5);


    item hat Eigenschaften, u.a. Position und Used.

    Dabei habe ich eine große Liste, entnehme 5 Stück deren Eigenschaft noch nicht Used = true gesetzt ist.
     Mit diesen 5 items bearbeite ich etwas.

    Nach dem Entnehmen, sollte ich die Eigenschaft auf true setzen.
    Wie macht man das?
    Die Hauptliste wieder durchlaufen und dann gezielt abändern?
    Oder gibt es da bessere Lösungen?

    Kurzum ich habe eine Liste, entnehme 5 Stück, dann die nächsten 5 unbearbeiteten usw.

       

    Gruß, Oliver
    Donnerstag, 8. Juni 2017 16:40

Antworten

  • Hallo Oliver,

    soweit ich Linq kenne kann man nicht direkt Änderungen im Ausdruck vornehmen.

    Was aber geht ist die von Dir erzeugte Liste nachträglich zu modifizieren.

    var list = ctn.Items
        .Where(t=> t.Used == false)
        .OrderBy(t => t.Position)
        .Take(5);
    foreach (var item in list) {
        item.Used = true;
    }

    Da list tatsächlich auf die Elemente verweist, wird die Eigenschaft auch in der ursprünglichen Liste verändert.

    Grüße

    Roland

    Habe gerade gesehen es gab eine Überschneidung mit Alexander's Beitrag. Das Let kannte ich nicht.
    Donnerstag, 8. Juni 2017 18:13
  • Hallo Oliver,

    wie Franz bereits schreibt: LINQ ist eine Abfragesprache (Q = Query), und enthält (bewusst) keine Methoden zur Datenmanipulation. Auch vom "Basteln" von Erweiterungen in der Richtung sollte man Abstand nehmen. Denn je komplexer die Abfrage wird, um so unbeherrschbarer werden mögliche Seiteneffekte. Spätestens in Verbindung mit asynchronen Methoden wird man schnell mit unangenehmen Überraschungen erleben.

    Eine LINQ Abfrage liefert ein IEnumerable<T> und die damit gelieferten Werte kann man wie gewohnt mit foreach durchlaufen und verändern - Deine Benenmung als list ist insofern nicht ganz richtig. Die Abfrage kannst Du mehrfach verwenden, womit du die Definition einmalig erstellen kannst.

    Wenn Du die Sorgen über die Geschwindigkeit machst, wäre eine Möglichkeit, die noch nicht verwendeten Elemente in eine als Verweise in einer separaten Liste zu speichern, daraus jeweils fünf entnehmen und sie nach Verwendung aus dieser Liste löschen. (Was aber nur funktioniert, wenn nicht mehrere Tasks auf die gleiche Aufgabe angesetzt werden - s . o.)

    Gruß Elmar

    Freitag, 9. Juni 2017 07:06
    Beantworter
  • Hallo Oliver,
    da hast Du zunächst 2 Ansätze.
    Der erste wäre ein Let. 
    Der zweite ist 5 Neue Elemente vom Typ items zu erzeugen und hierbei Used=true zu setzten.

    Hier eine Kombination aus beiden. Hier wird ein anonymer Type erzeugt.

    var list = (from t in ctn.Items where t.Used == false 
       OrderBy t.Position select new { Used= false, Position =t.Position})     .Take(5);

    Möchtest Du mit Items herauskommen soll ein select new items { Used=false , Position = t.Position} ..... das erledigen.
    Siehe: https://stackoverflow.com/questions/9480023/using-the-let-kewword-in-a-linq-query-with-ef-4-3

    HTH 

    Grüße Alexander

    Donnerstag, 8. Juni 2017 18:08

Alle Antworten

  • Hallo Oliver,
    da hast Du zunächst 2 Ansätze.
    Der erste wäre ein Let. 
    Der zweite ist 5 Neue Elemente vom Typ items zu erzeugen und hierbei Used=true zu setzten.

    Hier eine Kombination aus beiden. Hier wird ein anonymer Type erzeugt.

    var list = (from t in ctn.Items where t.Used == false 
       OrderBy t.Position select new { Used= false, Position =t.Position})     .Take(5);

    Möchtest Du mit Items herauskommen soll ein select new items { Used=false , Position = t.Position} ..... das erledigen.
    Siehe: https://stackoverflow.com/questions/9480023/using-the-let-kewword-in-a-linq-query-with-ef-4-3

    HTH 

    Grüße Alexander

    Donnerstag, 8. Juni 2017 18:08
  • Hallo Oliver,

    soweit ich Linq kenne kann man nicht direkt Änderungen im Ausdruck vornehmen.

    Was aber geht ist die von Dir erzeugte Liste nachträglich zu modifizieren.

    var list = ctn.Items
        .Where(t=> t.Used == false)
        .OrderBy(t => t.Position)
        .Take(5);
    foreach (var item in list) {
        item.Used = true;
    }

    Da list tatsächlich auf die Elemente verweist, wird die Eigenschaft auch in der ursprünglichen Liste verändert.

    Grüße

    Roland

    Habe gerade gesehen es gab eine Überschneidung mit Alexander's Beitrag. Das Let kannte ich nicht.
    Donnerstag, 8. Juni 2017 18:13
  • Hallo Oliver,

    wie Franz bereits schreibt: LINQ ist eine Abfragesprache (Q = Query), und enthält (bewusst) keine Methoden zur Datenmanipulation. Auch vom "Basteln" von Erweiterungen in der Richtung sollte man Abstand nehmen. Denn je komplexer die Abfrage wird, um so unbeherrschbarer werden mögliche Seiteneffekte. Spätestens in Verbindung mit asynchronen Methoden wird man schnell mit unangenehmen Überraschungen erleben.

    Eine LINQ Abfrage liefert ein IEnumerable<T> und die damit gelieferten Werte kann man wie gewohnt mit foreach durchlaufen und verändern - Deine Benenmung als list ist insofern nicht ganz richtig. Die Abfrage kannst Du mehrfach verwenden, womit du die Definition einmalig erstellen kannst.

    Wenn Du die Sorgen über die Geschwindigkeit machst, wäre eine Möglichkeit, die noch nicht verwendeten Elemente in eine als Verweise in einer separaten Liste zu speichern, daraus jeweils fünf entnehmen und sie nach Verwendung aus dieser Liste löschen. (Was aber nur funktioniert, wenn nicht mehrere Tasks auf die gleiche Aufgabe angesetzt werden - s . o.)

    Gruß Elmar

    Freitag, 9. Juni 2017 07:06
    Beantworter
  • Hallo Elmar,
    ja da hast Du recht.
    Nur Roland hat recht, da list tatsächlich auf die Elemente verweist.
    Ist ja eigentlich fatal.
    Hätte ich so nicht erwartet.
    Gruß, Oliver
    Freitag, 9. Juni 2017 15:30