Tôi muốn thay đổi một số thuộc tính của đối tượng kết quả truy vấn LINQ mà không tạo đối tượng mới và đặt thủ công mọi thuộc tính. Điều này có thể không?
Thí dụ:
var list = from something in someList
select x // but change one property
Tôi muốn thay đổi một số thuộc tính của đối tượng kết quả truy vấn LINQ mà không tạo đối tượng mới và đặt thủ công mọi thuộc tính. Điều này có thể không?
Thí dụ:
var list = from something in someList
select x // but change one property
Câu trả lời:
Tôi không chắc cú pháp truy vấn là gì. Nhưng đây là ví dụ biểu thức LINQ mở rộng.
var query = someList.Select(x => { x.SomeProp = "foo"; return x; })
Những gì nó làm là sử dụng một phương thức nặc danh vs và biểu thức. Điều này cho phép bạn sử dụng một số câu lệnh trong một lambda. Vì vậy, bạn có thể kết hợp hai thao tác thiết lập thuộc tính và trả lại đối tượng vào phương thức hơi súc tích này.
ToList()
trước đó dường như để làm các mẹo. Không chắc chắn tại sao bạn có được điều đó mặc dù. Nếu đó là Entity Framework, nó cũng không hoạt động với điều đó.
Nếu bạn chỉ muốn cập nhật thuộc tính trên tất cả các yếu tố thì
someList.All(x => { x.SomeProp = "foo"; return true; })
Tôi thích cái này Nó có thể được kết hợp với các lệnh linq khác.
from item in list
let xyz = item.PropertyToChange = calcValue()
select item
Không nên có bất kỳ phép thuật LINQ nào ngăn bạn làm điều này. Đừng sử dụng phép chiếu mặc dù điều đó sẽ trả về một loại ẩn danh.
User u = UserCollection.FirstOrDefault(u => u.Id == 1);
u.FirstName = "Bob"
Điều đó sẽ sửa đổi đối tượng thực, cũng như:
foreach (User u in UserCollection.Where(u => u.Id > 10)
{
u.Property = SomeValue;
}
Không thể với các toán tử truy vấn tiêu chuẩn - đó là Truy vấn tích hợp ngôn ngữ, không phải là Cập nhật tích hợp ngôn ngữ. Nhưng bạn có thể ẩn cập nhật của mình trong các phương thức mở rộng.
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;
}
}
}
Bây giờ bạn có thể sử dụng nó như sau.
cars.Where(car => car.Color == Color.Blue).ChangeColorTo(Color.Red);
UPDATE
, DELETE
và INSERT
. Vì vậy, tôi sẽ không tranh luận rằng ngữ nghĩa là thứ ngăn chặn chức năng này.
Nếu bạn muốn cập nhật các mục bằng một Where
mệnh đề, sử dụng .Where (...) sẽ cắt bớt kết quả của bạn nếu bạn thực hiện:
mylist = mylist.Where(n => n.Id == ID).Select(n => { n.Property = ""; return n; }).ToList();
Bạn có thể thực hiện cập nhật cho (các) mục cụ thể trong danh sách như sau:
mylist = mylist.Select(n => { if (n.Id == ID) { n.Property = ""; } return n; }).ToList();
Luôn trả lại hàng ngay cả khi bạn không thực hiện bất kỳ thay đổi nào. Bằng cách này, nó sẽ được giữ trong danh sách.
Chúng tôi thường chạy vào đây, nơi chúng tôi muốn bao gồm một giá trị chỉ mục và các chỉ số đầu tiên và cuối cùng trong một danh sách mà không tạo ra một đối tượng mới. Điều này cho phép bạn biết vị trí của mục trong danh sách, bảng liệt kê, v.v. mà không phải sửa đổi lớp hiện có và sau đó biết bạn đang ở mục đầu tiên trong danh sách hay cuối cùng.
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;
}))
Bạn chỉ có thể mở rộng bất kỳ lớp nào bằng cách sử dụng:
public abstract class IteratorExtender {
public int ListIndex { get; set; }
public bool IsFirst { get; set; }
public bool IsLast { get; set; }
}
public class Item : IteratorExtender {}
Vì tôi đã không tìm thấy câu trả lời ở đây mà tôi cho là giải pháp tốt nhất, theo cách của tôi:
Có thể sử dụng "Chọn" để sửa đổi dữ liệu, nhưng chỉ với một mẹo. Dù sao, "Chọn" không được thực hiện cho điều đó. Nó chỉ thực hiện sửa đổi khi được sử dụng với "ToList", bởi vì Linq không thực hiện trước khi dữ liệu cần thiết. Dù sao, giải pháp tốt nhất là sử dụng "foreach". Trong đoạn mã sau, bạn có thể thấy:
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);
;
}
}
}
Trước khi "foreach", bạn cũng có thể thực hiện lựa chọn linq ...
var item = (from something in someList
select x).firstordefault();
Sẽ nhận được item
, và sau đó bạn có thể làmitem.prop1=5;
để thay đổi tài sản cụ thể.
Hoặc bạn có muốn nhận danh sách các mục từ db và để nó thay đổi thuộc tính prop1
trên mỗi mục trong danh sách được trả về thành giá trị đã chỉ định không? Nếu vậy bạn có thể làm điều này (Tôi đang làm nó trong VB vì tôi biết nó tốt hơn):
dim list = from something in someList select x
for each item in list
item.prop1=5
next
( list
sẽ chứa tất cả các mục được trả lại cùng với các thay đổi của bạn)
for each
vòng lặp.
Năm 2020 tôi sử dụng MoreLinq
Pipe
phương pháp. 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"