我想更改 LINQ 查询结果对象的某些属性,而无需创建新对象并手动设置每个属性。这可能吗?
例子:
var list = from something in someList
select x // but change one property
我不确定查询语法是什么。但这里是扩展的 LINQ 表达式示例。
var query = someList.Select(x => { x.SomeProp = "foo"; return x; })
这样做是使用匿名方法 vs 和表达式。这允许您在一个 lambda 中使用多个语句。所以你可以将设置属性和返回对象这两个操作组合成这个有点简洁的方法。
如果您只想更新所有元素的属性,那么
someList.All(x => { x.SomeProp = "foo"; return true; })
我更喜欢这个。它可以与其他 linq 命令结合使用。
from item in list
let xyz = item.PropertyToChange = calcValue()
select item
不应该有任何 LINQ 魔法阻止你这样做。不要使用投影,尽管它会返回一个匿名类型。
User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"
这将修改真实对象,以及:
foreach (User u in UserCollection.Where(u => u.Id > 10)
{
u.Property = SomeValue;
}
使用标准查询运算符是不可能的 - 它是语言集成查询,而不是语言集成更新。但是您可以在扩展方法中隐藏您的更新。
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;
}
}
}
现在您可以按如下方式使用它。
cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
UPDATE
、DELETE
和 INSERT
公开了能力。所以我不会争辩说语义是阻止这个功能的东西。
如果您想使用 Where
子句更新项目,则使用 .Where(...) 会截断您的结果,如果您这样做:
list = list.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();
您可以对列表中的特定项目进行更新,如下所示:
list = list.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();
即使您没有进行任何更改,也请始终返回项目。这样,它将保留在列表中。
我们经常遇到这种情况,我们希望在列表中包含索引值以及第一个和最后一个指标而不创建新对象。这使您可以知道项目在列表、枚举等中的位置,而无需修改现有类,然后知道您是在列表中的第一项还是最后一项。
foreach (Item item in this.Items
.Select((x, i) => {
x.ListIndex = i;
x.IsFirst = i == 0;
x.IsLast = i == this.Items.Count-1;
return x;
}))
您可以使用以下方法简单地扩展任何类:
public abstract class IteratorExtender {
public int ListIndex { get; set; }
public bool IsFirst { get; set; }
public bool IsLast { get; set; }
}
public class Item : IteratorExtender {}
2020 年我使用 MoreLinq
Pipe
方法。 https://morelinq.github.io/2.3/ref/api/html/M_MoreLinq_MoreEnumerable_Pipe__1.htm
由于我没有在这里找到我认为最好的解决方案的答案,所以我的方式是:
使用“选择”来修改数据是可能的,但只是一个技巧。无论如何,“选择”不是为此而设计的。它只是在与“ToList”一起使用时执行修改,因为 Linq 在需要数据之前不会执行。无论如何,最好的解决方案是使用“foreach”。在以下代码中,您可以看到:
class Person
{
public int Age;
}
class Program
{
private static void Main(string[] args)
{
var persons = new List<Person>(new[] {new Person {Age = 20}, new Person {Age = 22}});
PrintPersons(persons);
//this doesn't work:
persons.Select(p =>
{
p.Age++;
return p;
});
PrintPersons(persons);
//with "ToList" it works
persons.Select(p =>
{
p.Age++;
return p;
}).ToList();
PrintPersons(persons);
//This is the best solution
persons.ForEach(p =>
{
p.Age++;
});
PrintPersons(persons);
Console.ReadLine();
}
private static void PrintPersons(List<Person> persons)
{
Console.WriteLine("================");
foreach (var person in persons)
{
Console.WriteLine("Age: {0}", person.Age);
;
}
}
}
在“foreach”之前,您还可以进行 linq 选择...
var item = (from something in someList
select x).firstordefault();
将获取 item
,然后您可以执行 item.prop1=5;
来更改特定属性。
或者您是否想从数据库中获取项目列表并让它将该返回列表中每个项目的属性 prop1
更改为指定值?如果是这样,您可以这样做(我在 VB 中这样做,因为我更了解它):
dim list = from something in someList select x
for each item in list
item.prop1=5
next
(list
将包含随您的更改返回的所有项目)
for each
循环。
这是最简单的解决方案:list.Where(t => t.Id == 1).ToList().ForEach(t => t.Property = "something");
尝试和工作,从这里引用:https://visualstudiomagazine.com/articles/2019/07/01/updating-linq.aspx
我遇到了确切的要求(OP的问题),但我没有看到使用表达式在上面的任何地方回答。
假设 x
是 MyType
类型,您可以调用返回 MyType
的方法,该方法接受 x
。在该方法中,您可以进行所需的所有修改。代码看起来像这样。
var list = from something in someList
select GetModifiedObject(x); // but change one property
private MyType GetModifiedObject(MyType x)
{
x.Property1 = "Changed Value";
return x;
}
User u = UserCollection.Single(u => u.Id == 1);
u.FirstName = "Bob"
ToList()
似乎可以解决问题。不知道为什么你会得到那个。如果它是实体框架,它也不适用。