2013-09-21 9 views
109

ja dostaję ten błąd dla zapytania poniżejNie można utworzyć stałą wartość typu Tylko prymitywnych typów lub typy wyliczeniowe są obsługiwane w tym kontekście

Nie można utworzyć stałą wartość typu API.Models.PersonProtocol. Tylko prymitywne typy lub typy wyliczeniowe są obsługiwane w tym kontekście

ppCombined poniżej jest IEnumerable przedmiotem PersonProtocolType, który jest zbudowany przez concat 2 PersonProtocol list.

Dlaczego to się nie udaje? Czy nie możemy użyć klauzuli LINQ JOIN wewnątrz SELECT z JOIN?

var persons = db.Favorites 
    .Where(x => x.userId == userId) 
    .Join(db.Person, x => x.personId, y => y.personId, (x, y) => 
     new PersonDTO 
     { 
      personId = y.personId, 
      addressId = y.addressId,     
      favoriteId = x.favoriteId, 
      personProtocol = (ICollection<PersonProtocol>) ppCombined 
       .Where(a => a.personId == x.personId) 
       .Select(b => new PersonProtocol() 
       { 
        personProtocolId = b.personProtocolId, 
        activateDt = b.activateDt, 
        personId = b.personId 
       }) 
     }); 
+0

Related: [ LINQ, Nie można utworzyć stałej wartości typu XXX. W tym kontekście obsługiwane są tylko typy pierwotne lub typy wyliczeniowe] (http://stackoverflow.com/q/13405568/456814). –

+0

Powiązane: [Nie można utworzyć stałej wartości - tylko typy pierwotne] (http://stackoverflow.com/q/10862491/456814). –

Odpowiedz

157

To nie może działać, ponieważ ppCombined jest zbiorem obiektów w pamięci i nie można dołączyć do zestawu danych w bazie danych z innego zestawu danych, które są w pamięci. Można spróbować zamiast wydobyć przefiltrowane elementy personProtocol z kolekcji ppCombined w pamięci po pobraniu inne właściwości z bazy danych:

var persons = db.Favorites 
    .Where(f => f.userId == userId) 
    .Join(db.Person, f => f.personId, p => p.personId, (f, p) => 
     new // anonymous object 
     { 
      personId = p.personId, 
      addressId = p.addressId, 
      favoriteId = f.favoriteId, 
     }) 
    .AsEnumerable() // database query ends here, the rest is a query in memory 
    .Select(x => 
     new PersonDTO 
     { 
      personId = x.personId, 
      addressId = x.addressId, 
      favoriteId = x.favoriteId, 
      personProtocol = ppCombined 
       .Where(p => p.personId == x.personId) 
       .Select(p => new PersonProtocol 
       { 
        personProtocolId = p.personProtocolId, 
        activateDt = p.activateDt, 
        personId = p.personId 
       }) 
       .ToList() 
     }); 
+3

Kluczowym elementem dla mnie było dodanie .AsEnumerable() // zapytanie do bazy danych kończy się tutaj, reszta to zapytanie w pamięci – Sameer

+2

@Slauma Więc jeśli martwię się wydajnością, powinienem tego unikać, ponieważ ładowałoby to wszystkie dane w pamięci najpierw, a następnie zapytaj go. Czy powinienem pisać surowy sql dla tego scenariusza? – Arvand

+0

Wygląda na to, że @Arvand ma świetny punkt. Jeśli masz dużo rekordów przed filtrem, może to zaowocować ogromną ilością dostępnych zasobów pamięci. – spadelives

2

Nie wiem, czy ktoś szuka tego. Miałem ten sam problem. Wybór w zapytaniu, a następnie zrobienie tego gdzie (lub dołączenie) i użycie zmiennej select rozwiązało problem dla mnie. (problem był w kolekcji "Reintegraties" dla mnie)

query.Select(zv => new 
      { 
       zv, 
       rId = zv.this.Reintegraties.FirstOrDefault().Id 
      }) 
      .Where(x => !db.Taken.Any(t => t.HoortBijEntiteitId == x.rId 
              && t.HoortBijEntiteitType == EntiteitType.Reintegratie 
              && t.Type == TaakType)) 
      .Select(x => x.zv); 

nadzieję, że to pomaga nikomu.

+5

'zv.this.Reintegraties.FirstOrDefault(). Id' potencjał NullReferenceException –

0

W moim przypadku udało mi się rozwiązać ten problem w następujący sposób:

zmieniłem kod z tego:

var r2 = db.Instances.Where(x => x.Player1 == inputViewModel.InstanceList.FirstOrDefault().Player2 && x.Player2 == inputViewModel.InstanceList.FirstOrDefault().Player1).ToList(); 

do tego:

var p1 = inputViewModel.InstanceList.FirstOrDefault().Player1; 
var p2 = inputViewModel.InstanceList.FirstOrDefault().Player2; 
var r1 = db.Instances.Where(x => x.Player1 == p1 && x.Player2 == p2).ToList();