LINQ:选择一个对象并更改某些属性而不创建新对象

Rob*_*olk 205 c# linq

使用LINQ,如果我想执行一些查询并从查询中返回对象,但只更改该对象中的某些属性,如何在不创建新对象的情况下执行此操作并手动设置每个属性?这可能吗?

例:

var list = from something in someList
           select x // but change one property
Run Code Online (Sandbox Code Playgroud)

Jar*_*Par 360

我不确定查询语法是什么.但这是扩展的LINQ表达式示例.

var query = someList.Select(x => { x.SomeProp = "foo"; return x; })
Run Code Online (Sandbox Code Playgroud)

这样做是使用匿名方法vs和表达式.这允许您在一个lambda中使用多个语句.因此,您可以组合设置属性的两个操作,并将对象返回到这个有点简洁的方法中.

  • 我得到"一个语句体的lambda表达式无法转换为表达式树"错误.它不适用于LINQ to SQL,有什么建议吗? (33认同)
  • @surya这正是我用Linq to SQL尝试时得到的消息.在此之前添加`ToList()`似乎可以解决问题.不知道为什么你会这样做.如果它是实体框架,它也不适用. (10认同)
  • 顺便说一下,由于显而易见的原因,这在LINQ to SQL中不起作用. (5认同)
  • @surya当你调用ToList()时,你实际上是将数据带回内存.所以它实际上不再是Linq to SQL了. (5认同)
  • @Rob,不容易.实现这一目标的语法是......最多不可读.var query = from list in list select((Func <Foo>)(()=> {it.x = 42; return it;}))(); (3认同)
  • @spiderdevil +1给你 - 难道你不是只是讨厌这个差距吗?这不是我第一次遇到代码仅适用于Linq to Object而不是Linq to SQL/EF的情况.这可能是一个解决方案[这里](http://stackoverflow.com/a/466266/603807),但我还没有尝试使用它,因为我没有时间. (2认同)
  • 根据埃里克·利珀特(Eric Lippert)的说法,该解决方案“ ...效率低下,令人困惑,无法维护,不必要,浪费,取决于查询运算符的实现细节,没有推广到非LINQ-to-objects场景以及滥用运算符的意图回答问题,而不产生副作用。”。看到他对[此答案]的评论(/sf/answers/3317858981/) (2认同)

Jon*_*kes 57

如果您只想更新所有元素的属性,那么

someList.All(x => { x.SomeProp = "foo"; return true; })
Run Code Online (Sandbox Code Playgroud)

  • 在EF(实体框架)中:要替换IEnumerable的所有对象上的属性,接受的答案对我有用.为我工作的代码:var myList = _db.MyObjects.Where(o => o.MyProp =="bar").AsEnumerable().选择(x => {x.SomeProp ="foo";返回x;}) ; (3认同)

Jan*_*ník 31

我更喜欢这个.它可以与其他linq命令结合使用.

from item in list
let xyz = item.PropertyToChange = calcValue()
select item
Run Code Online (Sandbox Code Playgroud)

  • 不是一个漂亮的解决方案,但效果很好.谢谢. (4认同)
  • 表达式树不能包含赋值 (3认同)

Jos*_*den 21

应该没有任何LINQ魔法阻止你这样做.虽然这将返回匿名类型,但不要使用投影.

User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"
Run Code Online (Sandbox Code Playgroud)

这将修改真实对象,以及:

foreach (User u in UserCollection.Where(u => u.Id > 10)
{
    u.Property = SomeValue;
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ner 10

标准查询运算符是不可能的 - 它是语言集成查询,而不是语言集成更新.但您可以在扩展方法中隐藏更新.

public static class UpdateExtension
{
    public static IEnumerable<Car> ChangeColorTo(
       this IEnumerable<Car> cars, Color color)
    {
       foreach (Car car in cars)
       {
          car.Color = color;
          yield return car;
       }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以按如下方式使用它.

cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
Run Code Online (Sandbox Code Playgroud)

  • LINQ取代了SQL,它代表Structured*Query*语言,但它仍然暴露了"UPDATE","DELETE"和"INSERT"的能力.所以我不认为语义是阻止这个功能的东西. (3认同)

Pie*_*rre 7

如果你想用Where子句更新项目,如果你这样做,使用 .Where(...) 将截断你的结果:

list = list.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();
Run Code Online (Sandbox Code Playgroud)

您可以对列表中的特定项目进行更新,如下所示:

list = list.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();
Run Code Online (Sandbox Code Playgroud)

即使您不进行任何更改,也始终退回商品。这样它就会被保留在列表中。