Metody nie można przetłumaczyć na wyrażenie sklepu

89

Widziałem, że ten kod działa z LINQ to SQL, ale kiedy używam Entity Framework, zgłasza ten błąd:

LINQ to Entities nie rozpoznaje metody „System.Linq.IQueryable” 1 [MyProject.Models.CommunityFeatures] GetCommunityFeatures () ”i nie można jej przetłumaczyć na wyrażenie sklepu”.

Oto kod repozytorium:

public IQueryable<Models.Estate> GetEstates()
{
    return from e in entity.Estates
           let AllCommFeat = GetCommunityFeatures()
           let AllHomeFeat = GetHomeFeatures()
           select new Models.Estate
                      {
                                EstateId = e.EstateId,
                                AllHomeFeatures = new LazyList<HomeFeatures>(AllHomeFeat),
                                AllCommunityFeatures = new LazyList<CommunityFeatures>(AllCommFeat)
                      };
}

public IQueryable<Models.CommunityFeatures> GetCommunityFeatures()
{
    return from f in entity.CommunityFeatures
           select new CommunityFeatures
                      {
                          Name = f.CommunityFeature1,
                          CommunityFeatureId = f.CommunityFeatureId
                      };
}

public IQueryable<Models.HomeFeatures> GetHomeFeatures()
{
    return from f in entity.HomeFeatures
           select new HomeFeatures()
           {
               Name = f.HomeFeature1,
               HomeFeatureId = f.HomeFeatureId
           };
}

LazyList to lista, która rozszerza możliwości IQueryable.

Czy ktoś mógłby wyjaśnić, dlaczego pojawia się ten błąd?

Shawn Mclean
źródło

Odpowiedzi:

115

Przyczyna: zgodnie z projektem LINQ to Entities wymaga przetłumaczenia całego wyrażenia zapytania LINQ na zapytanie serwera. Tylko kilka nieskorelowanych podwyrażeń (wyrażeń w zapytaniu, które nie zależą od wyników z serwera) jest ocenianych na kliencie przed przetłumaczeniem zapytania. Dowolne wywołania metod, które nie mają znanego tłumaczenia, jak w tym przypadku GetHomeFeatures (), nie są obsługiwane.
Aby być bardziej szczegółowym, LINQ to Entities obsługują tylko konstruktory bez parametrów i inicjatory .

Rozwiązanie: w związku z tym, aby obejść ten wyjątek, należy scalić zapytanie podrzędne z zapytaniem głównym dla GetCommunityFeatures () i GetHomeFeatures ()zamiast bezpośrednio wywoływać metody z poziomu zapytania LINQ. Ponadto występuje problem w wierszach, w których próbowano utworzyć wystąpienie nowego wystąpienia LazyList przy użyciu jego sparametryzowanych konstruktorów, tak jak można było to zrobić w LINQ to SQL . W tym celu rozwiązaniem byłoby przełączenie się na ocenę klienta LINQ zapytań (LINQ to Objects). Będzie to wymagało wywołania metody AsEnumerable dla zapytań LINQ to Entities przed wywołaniem konstruktora LazyList.

Coś takiego powinno działać:

public IQueryable<Models.Estate> GetEstates()
{
    return from e in entity.Estates.AsEnumerable()
       let AllCommFeat = from f in entity.CommunityFeatures
                         select new CommunityFeatures {
                             Name = f.CommunityFeature1,
                             CommunityFeatureId = f.CommunityFeatureId
                         },
       let AllHomeFeat = from f in entity.HomeFeatures
                         select new HomeFeatures() {
                             Name = f.HomeFeature1,
                             HomeFeatureId = f.HomeFeatureId
                         },
       select new Models.Estate {
            EstateId = e.EstateId,
            AllHomeFeatures = new LazyList<HomeFeatures>(AllHomeFeat),
            AllCommunityFeatures = new LazyList<CommunityFeatures>(AllCommFeat)
       };
}


Więcej informacji: Proszę spojrzeć na LINQ podmiotom, co nie jest obsługiwane? po więcej informacji. Sprawdź również LINQ to Entities, Obejścia dotyczące tego, co nie jest obsługiwane, aby uzyskać szczegółowe omówienie możliwych rozwiązań. (Oba linki są wersjami z pamięci podręcznej, ponieważ oryginalna witryna internetowa jest wyłączona)

Morteza Manavi
źródło