Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ - update a field within where clause

Tags:

linq

My object hierarchy is like this:

class Detail
{
    public List<Row> Rows { get; set; }
}

class Row
{
    public List<Column> Columns { get; set; }
}

class Column
{
    public string Name { get; set; }
    public bool IsUpdated { get; set; }
}

I want to set column.IsUpdated = true where column.Name = "id". I am trying this, it doesn't work.

detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Select(c => c.IsUpdated = true));
like image 346
GaneshT Avatar asked Mar 28 '12 21:03

GaneshT


2 Answers

The philosophy of LINQ is to not have side effects. That's why on purpose it does not make it easy for you to do this. You could do it either with a classic

var cols = details.Rows.SelectMany(r => r.Columns)
                       .Where(c => c.Name.ToLower().Equals("id"));
foreach(var col in cols) {
    col.IsUpdated = true;
}

or by using List.ForEach, but in a different manner:

details.Rows.SelectMany(r => r.Columns)
            .Where(c => c.Name.ToLower().Equals("id")).ToList()
            .ForEach(c => { c.IsUpdated = true });
like image 166
Jon Avatar answered Oct 18 '22 10:10

Jon


LINQ is really intended for querying data, not changing values within the data. If you want to make an entire new detail item, you could do that:

var newDetail = new Detail 
    {
        Rows = detail.Rows.Select(r => new Row 
                                            {
                                                 Columns = r.Columns.Select(c => new Column { Name = c.Name, IsUpdated = c.Name.ToLower() == "id" ? true : c.IsUpdated }).ToList() 
                                            })
                          .ToList() 
    };

Note that the above would be cleaner, most likely, if you added constructors for your types, as well.

That being said, if you want to update it in place, like you were showing, I would just use loops:

foreach(var row in detail.Rows)
    foreach(var col in row.Columns)
        if (col.Name.ToLower() == "id")
            col.IsUpdated = true;

I find that far easier to follow, especially in this case.

like image 33
Reed Copsey Avatar answered Oct 18 '22 10:10

Reed Copsey