Pytanie "Nowe" wewnątrz projekcji typu betonu jest wywoływane tylko raz


Mam proste zapytanie Linq2Sql:

var result = from t in MyContext.MyItems
             select new MyViewModelClass()
             {
                 FirstProperty = t,
                 SecondProperty = new SomeLinq2SqlEntity()
             }      

Problem polega na tym, że wydaje się, że new SomeLinq2SqlEntity() jest wykonywane tylko raz dla sekwencji, więc wszystkie wystąpienia MyViewModelClass w wyniku kwerendy udostępnić link do jednego obiektu.

Aktualizacja: Oto jak szybko to sprawdzić:

result[0].SecondProperty.MyField = 10;

Używając debuggera mogę to sprawdzić MyField został ustawiony na 10 we wszystkich przypadkach.

Kiedy zamieniam zapytanie LINQ na foreach, działa ono zgodnie z oczekiwaniami:

  var result = from t in MyContext.MyItems select t;
  var list = new List<MyViewModelClass>();
  foreach (var item in result)
  {
      list.add(new MyViewModelClass()
             {
                 FirstProperty = item,
                 SecondProperty = new SomeLinq2SqlEntity()
             });       
  }

Nie znalazłem źródła problemu, ale post oznaczony jako asnwer zapewnia dobre obejście. Sprawdź ten opis, aby uzyskać szczegółowy opis: "nowe" wewnątrz projekcji typu betonu jest wywoływane tylko raz


12
2017-08-01 14:23


pochodzenie


powiedziałeś to wydaje się instancja jest wykonywana tylko raz. Jak to zweryfikowałeś? czy próbowałeś przeszukać jedną właściwość, aby zobaczyć wartość odzwierciedloną we wszystkich rzutowanych obiektach, czy też wydaje się, że tak jest, ponieważ tylko jeden obiekt jest później trwały lub coś innego? - Rune FS
Dodałem szybki test w dziale "aktualizacja". - artvolk
Jest to z pewnością coś wspólnego z linq do sql: podobny przykład w linq do obiektów var v = "abc".Select(c => new ObjectContainer() { o = new SomeClass() }); wyniki w SomeClass ctor nazywał się spodziewanym trzy czasy - AakashM
Co się dzieje, jeśli nie masz średnika na końcu (;) nowego wyrażenia? - John Saunders
To był mój błąd, kiedy napisałem kod do pytania, usunąłem średniki. - artvolk


Odpowiedzi:


Czy próbowałeś użyć dodania SomeLinq2SqlEntity obiekt z linq do obiektów?

var result = (from t in MyContext.MyItems
             select new
             {
                 FirstProperty = t
             })
             .AsEnumerable() 
             .Select(t => new MyViewModelClass()
             {
                 FirstProperty = t.FirstProperty ,
                 SecondProperty = new SomeLinq2SqlEntity();
             });   

2
2017-08-01 14:32



Dzięki! Koncepcyjnie to wydaje się być takie samo jak foreach rozwiązanie, byłem całkowicie pewien, że moja pierwsza próba będzie zachowywać się tak samo. Nie rozumiem, dlaczego to nie działa ... Jakieś pomysły? - artvolk


Prawdopodobnie ma to coś wspólnego z dziwactwem IQueryable wdrożenie Twojego dostawcy. Odpowiedź Aducciego wyodrębnia dane z bazy danych AsEnumerable() wywołuje i wykonuje zapytanie w tym zestawie, które różni się od wykonywania przez niego IQueryable.

Na przykład IQueryable buduje ExpressionTree które później parsuje zgodnie z konkretnym dostawcą (tj. raz wykonuje wspólny kod dla optymalizacji), podczas gdy IEnumerable akceptuje Func i wykonuje to, jak można się spodziewać.

Możesz przeczytać więcej tutaj:

http://msdn.microsoft.com/en-us/vcsharp/ff963710


4
2017-08-01 17:32



Korzystam z domyślnego dostawcy MS SQL LINQ2SQL na .NET 4.0. Czy to jest (dobrze znany) błąd? - artvolk
Nie jestem pewien, ale Afaik Linq2Sql jest nieco przestarzały i przestał działać, więc prawdopodobnie lepiej byłoby użyć Entity Framework. - Grozz
Jest nadal obsługiwany (ale wygląda na to, że nie ma żadnych nowych funkcji). Dana aplikacja została uruchomiona dawno temu, kiedy EF nie była tak dobra jak dzisiaj. - artvolk