Powiedz, że mam IQueryable<Car> cars.

Iteruję to takie jak:

foreach (Car c in cars)
{
    c.Doors = 2;
}

Dlaczego c.Doors zawiera oryginalną wartość po foreach, a nie zmienioną wartość?

Z góry dziękuję

0
Dante 21 luty 2012, 17:13

2 odpowiedzi

Najlepsza odpowiedź

Wskazałeś, że IQueryable jest wynikiem zapytania linq do encji, które nie jest poprawną instrukcją. MyDatabaseContext.Cars.Where(x => x.Name == "Test") zwraca obiekt IQueryable, który podczas iteracji wykonuje zapytanie w bazie danych. (Iteracja ma miejsce, gdy wykonujesz nad nią foreach). Więc nie zawiera jeszcze zestawu wyników, tylko zapytanie.

Dwukrotne wykonanie pętli nad samochodami generuje 2 identyczne zapytania do bazy danych i zwraca 2 identyczne zestawy wyników. Jeśli chcesz zachować dane. musisz wywołać ToArray lub ToList lub po manipulacji wykonaj zapisanie zmian przed ponownym wykonaniem iteracji.

1
Polity 21 luty 2012, 17:24

Iteracja po IQueryable pobiera zestaw wyników z bazy danych w trakcie, jak jestem pewien, że wiesz. To, co zaobserwowałem w tej i innych sytuacjach, to to, że ten wynik nie jest buforowany, więc często można zauważyć, że ponowne iterowanie po IQueryable spowoduje ponowne uruchomienie zapytania, a zatem Twoje modyfikacje nie zostaną zachowane, ponieważ otrzymujesz nowy zestaw wyników, na który ten kod nigdy nie miał wpływu.

Powodem, dla którego to działa, gdy najpierw wywołujesz ToList() i powtarzasz wynik, jest to, że ToList() pobiera i materializuje cały zestaw wyników, który nie jest już powiązany z zawartością bazy danych i jest tak naprawdę tylko kopię tego, co zwróciła baza danych.

Jedynym sposobem, aby upewnić się, że zmiany zostaną zachowane, jest działanie na lokalnej kopii danych, tj. podniesienie jej z obszaru IQueryable. Może to być tak proste, jak zapisanie IEnumerable zestawu wyników (tj. wyniku ToEnumerable()), który następnie zwróci ten sam zestaw wyników za każdym razem, gdy go wyliczasz, ale w przeciwieństwie do ToList() nie spowoduje to natychmiastowej oceny.

1
Matthew Walton 21 luty 2012, 17:29