ฉันต้องการเปลี่ยนคุณสมบัติบางอย่างของวัตถุผลลัพธ์การสืบค้น LINQ โดยไม่ต้องสร้างวัตถุใหม่และตั้งค่าคุณสมบัติทั้งหมดด้วยตนเอง เป็นไปได้ไหม
ตัวอย่าง:
var list = from something in someList
select x // but change one property
ฉันต้องการเปลี่ยนคุณสมบัติบางอย่างของวัตถุผลลัพธ์การสืบค้น 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 และ expression ที่ไม่ระบุชื่อ สิ่งนี้อนุญาตให้คุณใช้หลายประโยคในแลมบ์ดาเดียว ดังนั้นคุณสามารถรวมการดำเนินการทั้งสองของการตั้งค่าคุณสมบัติและส่งคืนวัตถุในวิธีการที่ค่อนข้างกระชับ
ToList()
ก่อนที่ดูเหมือนว่าจะทำเคล็ดลับ ไม่แน่ใจว่าทำไมคุณถึงได้รับ ถ้าเป็น Entity Framework มันจะไม่ทำงานกับสิ่งนั้น
หากคุณเพียงต้องการอัปเดตสถานที่ให้บริการในองค์ประกอบทั้งหมดแล้ว
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;
}
ไม่สามารถใช้ตัวดำเนินการแบบสอบถามมาตรฐานได้ - เป็น Language Query ไม่ใช่ Language Integrated Update แต่คุณสามารถซ่อนอัปเดตของคุณในวิธีการขยาย
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
ประโยคการใช้. ที่ไหน (... ) จะตัดทอนผลลัพธ์ของคุณหากคุณ:
mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();
คุณสามารถอัปเดตรายการที่ต้องการในรายการดังนี้:
mylist = mylist.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 {}
เนื่องจากฉันไม่พบคำตอบที่นี่ซึ่งฉันพิจารณาวิธีแก้ปัญหาที่ดีที่สุดมาที่นี่ในแบบของฉัน:
การใช้ "เลือก" เพื่อปรับเปลี่ยนข้อมูลเป็นไปได้ แต่มีเพียงกลอุบาย อย่างไรก็ตาม "Select" ไม่ได้ทำเพื่อสิ่งนั้น เพียงแค่เรียกใช้การปรับเปลี่ยนเมื่อใช้กับ "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
ลูป
ในปี 2020 ฉันใช้MoreLinq
Pipe
วิธีนี้ https://morelinq.github.io/2.3/ref/api/html/M_MoreLinq_MoreEnumerable_Pipe__1.htm
User u = UserCollection.Single(u => u.Id == 1);
u.FirstName = "Bob"