【问题标题】:LINQ - update a field within where clauseLINQ - 更新 where 子句中的字段
【发布时间】:2012-04-12 13:29:55
【问题描述】:

我的对象层次结构是这样的:

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; }
}

我想设置 column.IsUpdated = true where column.Name = "id"。 我正在尝试这个,它不起作用。

detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Select(c => c.IsUpdated = true));

【问题讨论】:

标签: linq


【解决方案1】:

LINQ 的理念是没有副作用。这就是为什么故意让你不容易做到这一点。你可以用经典来做到这一点

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

或使用List.ForEach,但方式不同:

details.Rows.SelectMany(r => r.Columns)
            .Where(c => c.Name.ToLower().Equals("id")).ToList()
            .ForEach(c => { c.IsUpdated = true });

【讨论】:

  • 嘿约翰。那么,如果由于某种原因需要更新数千行,您会怎么做?假设操作员单击一个按钮,然后您必须将所有状态为“x”的行更新为状态“Y”,这通过普通 SQL 可以轻松快速地进行。正确的?但是,如果您将所有内容都加载到内存中,则需要很长时间
【解决方案2】:

LINQ 真正用于查询数据,而不是更改数据中的值。如果你想制作一个全新的细节项目,你可以这样做:

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() 
    };

请注意,如果您也为您的类型添加了构造函数,那么上述内容很可能会更简洁。

话虽如此,如果您想就地更新它,就像您展示的那样,我只会使用循环:

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

我发现这更容易理解,尤其是在这种情况下。

【讨论】:

    【解决方案3】:

    您不应该使用 LINQ 改变集合的所有元素(尽管可以这样做,请参阅 this question)。只使用香草foreach 更简单、更易读。

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

    【讨论】:

      【解决方案4】:

      我只是让它像这样工作。效率低吗?而不是 .Select 我放了 .Any。它有效,但我不确定它是否在大数据上效率低下。如果是,我可以选择其中一个答案。

      detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Any(c => c.IsUpdated = true));
      

      【讨论】:

      • 它不起作用,因为 Select() 被懒惰地评估,而 Any() 是贪婪的。无论哪种方式,这都是一个非常糟糕的主意! Linq 查询的副作用是最糟糕的做法哦,编辑你的问题,不要发布答案来添加信息。
      【解决方案5】:

      试试这个。现在应该使用您已经尝试使用的相同概念更新“IsUpdated”。

      detail.Rows.ForEach(r => r.Columns.Where(c => c.Name.ToLower().Equals("id")).ToList<Column>().Select(c => {c.IsUpdated = true; return c;}));
      

      【讨论】:

        猜你喜欢
        • 2014-09-18
        • 1970-01-01
        • 2012-08-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多