LINQ: Wybierz obiekt i zmień niektóre właściwości bez tworzenia nowego obiektu
218
Chcę zmienić niektóre właściwości obiektu wynikowego zapytania LINQ bez tworzenia nowego obiektu i ręcznego ustawiania każdej właściwości. czy to możliwe?
Przykład:
varlist=from something in someList
select x // but change one property
Napisałem metodę rozszerzenia opartą na odpowiedzi JaredPara poniżej, która pozwala to osiągnąć za pomocą składni deklaratywnej, tak jak w moim przykładzie. Sprawdź to: blog.robvolk.com/2009/05/…
Nie jestem pewien, jaka jest składnia zapytania. Ale oto przykład rozszerzonego wyrażenia LINQ.
var query = someList.Select(x =>{ x.SomeProp="foo";return x;})
To robi to użyć anonimowej metody vs i wyrażenia. Pozwala to na użycie kilku instrukcji w jednej lambda. Możesz więc połączyć dwie operacje ustawiania właściwości i zwracania obiektu do tej nieco zwięzłej metody.
@Rob, Nie łatwo. Składnia umożliwiająca to działanie jest ... w najlepszym razie nieczytelna. var query = z listy w liście select ((Func <Foo>) (() => {it.x = 42; return it;})) ();
@spiderdevil +1 dla Ciebie - czy nie nienawidzisz różnic? To nie pierwszy raz, kiedy napotkałem sytuację, w której kod działa tylko dla Linq na Object, a nie Linq na SQL / EF. To może być rozwiązanie tutaj , ale nie próbowałem go jeszcze użyć, ponieważ nie mam czasu.
@surya To jest dokładnie wiadomość, którą otrzymałem, gdy próbowałem z Linq na SQL. Dodanie ToList()przed tym wydaje się załatwić sprawę. Nie jestem pewien, dlaczego to dostajesz. Jeśli jest to Entity Framework, to też z tym nie działa.
W EF (Entity Framework): aby zastąpić właściwość na wszystkich obiektach IEnumerable, zaakceptowana odpowiedź działała dla mnie. Działający kod dla mnie: var myList = _db.MyObjects.Where (o => o.MyProp == "bar"). AsEnumerable (). Wybierz (x => {x.SomeProp = "foo"; return x;}) ;
Podoba mi się, moje pytanie jest w pierwszym przykładzie, co jeśli jakieś u> 10 nie znajduje się na liście? Dodałem czek zerowy i wydaje się, że działa. Również LHS nazwałem u do v. +1. Bardzo zwięzłe.
Nie jest to możliwe w przypadku standardowych operatorów zapytań - jest to Zapytanie zintegrowane z językiem, a nie Aktualizacja zintegrowana z językiem. Ale możesz ukryć swoją aktualizację w metodach rozszerzenia.
publicstaticclassUpdateExtension{publicstaticIEnumerable<Car>ChangeColorTo(thisIEnumerable<Car> cars,Color color){foreach(Car car in cars){
car.Color= color;yieldreturn car;}}}
Dobrze LINQ zastępuje SQL, który stoi na Structured Query Language, ale wciąż naraża zdolność umiejętność UPDATE, DELETEi INSERT. Nie argumentowałbym więc, że semantyka jest tym, co zapobiega tej funkcji.
Często spotykamy się z tym, że chcemy dołączyć wartość indeksu oraz pierwszy i ostatni wskaźnik do listy bez tworzenia nowego obiektu. To pozwala poznać pozycję elementu na liście, wyliczenie itp. Bez konieczności modyfikowania istniejącej klasy, a następnie wiedzieć, czy jesteś na pierwszym elemencie na liście, czy na ostatnim.
foreach(Item item inthis.Items.Select((x, i)=>{
x.ListIndex= i;
x.IsFirst= i ==0;
x.IsLast= i ==this.Items.Count-1;return x;}))
Możesz po prostu rozszerzyć dowolną klasę, używając:
Ponieważ nie znalazłem tutaj odpowiedzi, którą uważam za najlepsze rozwiązanie, oto moja droga:
Używanie „Wybierz” do modyfikowania danych jest możliwe, ale z pewną sztuczką. W każdym razie „Select” nie jest do tego stworzony. Po prostu wykonuje modyfikację, gdy jest używana z „ToList”, ponieważ Linq nie wykonuje się przed potrzebą danych. W każdym razie najlepszym rozwiązaniem jest użycie „foreach”. W poniższym kodzie widać:
classPerson{publicintAge;}classProgram{privatestaticvoidMain(string[] args){var persons =newList<Person>(new[]{newPerson{Age=20},newPerson{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();}privatestaticvoidPrintPersons(List<Person> persons){Console.WriteLine("================");foreach(var person in persons){Console.WriteLine("Age: {0}", person.Age);;}}}
Przed „foreach” możesz również dokonać wyboru linq ...
var item =(from something in someList
select x).firstordefault();
Otrzymałbym item, a następnie możesz zrobić, item.prop1=5;aby zmienić konkretną właściwość.
A może chcesz uzyskać listę elementów z bazy danych i zmienić tę właściwość prop1dla każdego elementu na tej zwróconej liście na określoną wartość? Jeśli tak, możesz to zrobić (robię to w VB, ponieważ wiem to lepiej):
dim list=from something in someList select x
for each item inlist
item.prop1=5
next
( listbędzie zawierać wszystkie elementy zwrócone z Twoimi zmianami)
Używamy plików cookie i innych technologii śledzenia w celu poprawy komfortu przeglądania naszej witryny, aby wyświetlać spersonalizowane treści i ukierunkowane reklamy, analizować ruch w naszej witrynie, i zrozumieć, skąd pochodzą nasi goście.
Kontynuując, wyrażasz zgodę na korzystanie z plików cookie i innych technologii śledzenia oraz potwierdzasz, że masz co najmniej 16 lat lub zgodę rodzica lub opiekuna.