O método não pode ser traduzido em uma expressão de armazenamento

89

Eu vi esse código funcionar com LINQ to SQL, mas quando uso o Entity Framework, ele gera este erro:

LINQ to Entities não reconhece o método 'System.Linq.IQueryable'1 [MyProject.Models.CommunityFeatures] GetCommunityFeatures ()', e este método não pode ser traduzido em uma expressão de armazenamento.

O código do repositório é este:

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 é uma lista que amplia o poder de IQueryable.

Alguém poderia explicar por que esse erro ocorre?

Shawn Mclean
fonte

Respostas:

115

Motivo: por design, LINQ to Entities requer que toda a expressão de consulta LINQ seja convertida em uma consulta de servidor. Apenas algumas subexpressões não correlacionadas (expressões na consulta que não dependem dos resultados do servidor) são avaliadas no cliente antes da tradução da consulta. Chamadas de método arbitrárias que não têm uma tradução conhecida, como GetHomeFeatures () neste caso, não são suportadas.
Para ser mais específico, o LINQ to Entities oferece suporte apenas a construtores e inicializadores sem parâmetros .

Solução: Portanto, para superar essa exceção, você precisa mesclar sua subconsulta na principal para GetCommunityFeatures () e GetHomeFeatures ()em vez de invocar métodos diretamente de dentro da consulta LINQ. Além disso, há um problema nas linhas de que você estava tentando instanciar uma nova instância de LazyList usando seus construtores parametrizados, assim como você poderia estar fazendo no LINQ to SQL . Para isso, a solução seria mudar para a avaliação do cliente de consultas LINQ (LINQ to Objects). Isso exigirá que você invoque o método AsEnumerable para suas consultas LINQ to Entities antes de chamar o construtor LazyList.

Algo assim deve funcionar:

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)
       };
}


Mais informações: Por favor, dê uma olhada em LINQ to Entities, o que não é compatível? para mais informações. Além disso, verifique LINQ to Entities, soluções alternativas sobre o que não é suportado para uma discussão detalhada sobre as soluções possíveis. (Ambos os links são as versões em cache porque o site original está fora do ar)

Morteza Manavi
fonte